Merge lp:~cjwatson/britney/fix-sru-branching into lp:britney
- fix-sru-branching
- Merge into britney2
Proposed by
Colin Watson
Status: | Superseded |
---|---|
Proposed branch: | lp:~cjwatson/britney/fix-sru-branching |
Merge into: | lp:britney |
Diff against target: |
7295 lines (+7146/-0) (has conflicts) 28 files modified
README (+107/-0) britney (+516/-0) fauxpkg/FauxPackages (+59/-0) fauxpkg/README (+50/-0) fauxpkg/fauxpkg.py (+181/-0) fauxpkg/noremove.d/README (+3/-0) scripts/backlog-report (+86/-0) scripts/ood_report.py (+101/-0) scripts/udeb-report (+49/-0) update_out/.gitignore (+6/-0) update_out/Makefile (+33/-0) update_out/README (+32/-0) update_out/assert.c (+11/-0) update_out/britney-py.c (+871/-0) update_out/checklib.c (+185/-0) update_out/dpkg-lib.cpp (+34/-0) update_out/dpkg.c (+2013/-0) update_out/dpkg.h (+207/-0) update_out/freelist.c (+188/-0) update_out/freelist.h (+14/-0) update_out/index.html (+18/-0) update_out/memory.c (+389/-0) update_out/memory.h (+47/-0) update_out/memory2.c (+20/-0) update_out/memory3.c (+209/-0) update_out/templates.h (+277/-0) update_out/thoughts (+13/-0) update_out/update_out.py (+1427/-0) Text conflict in README |
To merge this branch: | bzr merge lp:~cjwatson/britney/fix-sru-branching |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Ubuntu Package Archive Administrators | Pending | ||
Review via email: mp+261537@code.launchpad.net |
This proposal has been superseded by a proposal from 2015-06-09.
Commit message
Make sure the hints branch always points to the right place, even if it's changed due to e.g. a series being released.
Description of the change
Make sure the hints branch always points to the right place, even if it's changed due to e.g. a series being released.
To post a comment you must log in.
Unmerged revisions
- 281. By Colin Watson
-
Make sure the hints branch always points to the right place, even if it's changed due to e.g. a series being released.
- 280. By Adam Conrad
-
vivid -> wily
- 279. By Iain Lane
- 278. By Steve Langasek
- 277. By Steve Langasek
- 276. By Steve Langasek
- 275. By Steve Langasek
- 274. By Steve Langasek
- 273. By Steve Langasek
- 272. By Colin Watson
-
Publish update_excuses.yaml and archive copies of it.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'README' | |||
2 | --- README 2006-06-17 13:45:56 +0000 | |||
3 | +++ README 2015-06-09 16:34:27 +0000 | |||
4 | @@ -1,5 +1,112 @@ | |||
5 | 1 | <<<<<<< TREE | ||
6 | 1 | README for britney v2.0 | 2 | README for britney v2.0 |
7 | 2 | ======================= | 3 | ======================= |
8 | 3 | 4 | ||
9 | 4 | Please write here some useful stuff. | 5 | Please write here some useful stuff. |
10 | 5 | 6 | ||
11 | 7 | ======= | ||
12 | 8 | Britney is run from /org/release.debian.org/britney. Some notes about | ||
13 | 9 | how it works, what to do and what not: | ||
14 | 10 | |||
15 | 11 | * the code is in code/b1, which is a git repo. Changes must be | ||
16 | 12 | approved by Release Managers first, and all changes must be commited | ||
17 | 13 | (i.e. nothing uncommited is allowed there). | ||
18 | 14 | |||
19 | 15 | Commit emails will be send to britney@release.debian.org, you can | ||
20 | 16 | subscribe to that if you want them (along with cron mail from | ||
21 | 17 | britney). | ||
22 | 18 | |||
23 | 19 | * the main script is code/b1/britney. It accepts a list of "actions" | ||
24 | 20 | to perform. See ~release/etc/crontab.release for the default list, | ||
25 | 21 | and see the "Actions" and "Re-running" sections below. | ||
26 | 22 | |||
27 | 23 | * input/ contains FauxPackages, edit if if you need, and an urgencies/ | ||
28 | 24 | subdirectory where dinstall places a summary of the uploads of that | ||
29 | 25 | day. | ||
30 | 26 | |||
31 | 27 | * Heidi/, ssh/: see the "save" action below. | ||
32 | 28 | |||
33 | 29 | * d-i/: udeb handling is done by the release team too. See d-i/README | ||
34 | 30 | for details (when Dato writes it; Dato takes care of udebs until then). | ||
35 | 31 | |||
36 | 32 | |||
37 | 33 | Actions | ||
38 | 34 | ======= | ||
39 | 35 | |||
40 | 36 | The main actions (read, the ones that are invoked from cron) are: | ||
41 | 37 | |||
42 | 38 | * urgencies: updates var/data/testing/Urgency with the data provided | ||
43 | 39 | by dinstall. | ||
44 | 40 | |||
45 | 41 | * bugs: fetches bug counts from bugs.debian.org. | ||
46 | 42 | |||
47 | 43 | * pkglists: generates all needed Packages files according to the | ||
48 | 44 | latest dinstall. | ||
49 | 45 | |||
50 | 46 | * run: the main action, running the update_out.py script. Takes | ||
51 | 47 | hints, packages files, and tries to migrate stuff. When done, it | ||
52 | 48 | writes a HeidiResult file used by "save" below *and rewrites the | ||
53 | 49 | var/data/testing/Packags_* files*. That is important. | ||
54 | 50 | |||
55 | 51 | * save: commits the HeidiResult provided by update_out above. This is | ||
56 | 52 | done by: | ||
57 | 53 | |||
58 | 54 | - taking HeidiResult, stripping unwanted stuff (faux packages), | ||
59 | 55 | and put the result into a file under Heidi/set, named after the | ||
60 | 56 | current timestamp. | ||
61 | 57 | |||
62 | 58 | - changing the "current" symlink under Heidi/set to point to this | ||
63 | 59 | new file, gzipping the previous current. | ||
64 | 60 | |||
65 | 61 | - signaling ftpmaster scripts to import the new file. This is done | ||
66 | 62 | with a ssh trigger, whose key is in ssh/. | ||
67 | 63 | |||
68 | 64 | IF YOU NEED TO UNDO ONE IMPORT: gunzip the previous file, point | ||
69 | 65 | the "current" symlink to it, and: | ||
70 | 66 | |||
71 | 67 | % ssh -2 -i % ~release/britney/ssh/ftp-master_trigger_key dak@ries.debian.org | ||
72 | 68 | |||
73 | 69 | * stats: copies the resulting update.OUTPUT and update.EXCUSES files | ||
74 | 70 | to www/britney, and checks for uninstallabilities. | ||
75 | 71 | |||
76 | 72 | |||
77 | 73 | Re-running | ||
78 | 74 | ========== | ||
79 | 75 | |||
80 | 76 | Re-runs can be incremental or not: | ||
81 | 77 | |||
82 | 78 | * incremental means that you run britney against the results of the | ||
83 | 79 | previous run. This is done by just issuing `./britney run`. | ||
84 | 80 | |||
85 | 81 | WARNING: even if you don't save the results of an incremental | ||
86 | 82 | re-run, following re-runs will start with the state the previous one | ||
87 | 83 | left. This means it's a very very bad idea to use incremental | ||
88 | 84 | re-runs to test force-hint hints; please always use a private | ||
89 | 85 | britney instead. | ||
90 | 86 | |||
91 | 87 | * non-incremental means that you start from scratch against the state | ||
92 | 88 | of the previous install. To do this, you need to do "pkglists" prior | ||
93 | 89 | to "run". | ||
94 | 90 | |||
95 | 91 | IF THERE WERE ANY SUCCESSFUL HINTS IN THE PREVIOUS RUN, YOU MUST | ||
96 | 92 | CHECK WITH THEIR OWNERS WHETHER IT'S OK TO RUN FROM SCRATCH. Or, in | ||
97 | 93 | the worst case, you should check whether they have cleaned up their | ||
98 | 94 | hints already, since in that case their work will be lost. | ||
99 | 95 | |||
100 | 96 | (For this reason it's not very wise to clean your hints before your | ||
101 | 97 | stuff is dinstalled.) | ||
102 | 98 | |||
103 | 99 | If you're satisfied with the result of your re-run, run `./britney save`. | ||
104 | 100 | |||
105 | 101 | |||
106 | 102 | Private britneys | ||
107 | 103 | ================ | ||
108 | 104 | |||
109 | 105 | It is ok to run private britneys if you nice them, though Ganneff | ||
110 | 106 | prefers if you don't do it while dinstall is running. | ||
111 | 107 | |||
112 | 108 | Do NOT run your britney against britney/var/data directly, use a | ||
113 | 109 | copy of your own. | ||
114 | 110 | |||
115 | 111 | TODO(dato): Some HOWTO here. | ||
116 | 112 | >>>>>>> MERGE-SOURCE | ||
117 | 6 | 113 | ||
118 | === added file 'britney' | |||
119 | --- britney 1970-01-01 00:00:00 +0000 | |||
120 | +++ britney 2015-06-09 16:34:27 +0000 | |||
121 | @@ -0,0 +1,516 @@ | |||
122 | 1 | #!/bin/bash | ||
123 | 2 | |||
124 | 3 | set -e | ||
125 | 4 | set -u | ||
126 | 5 | |||
127 | 6 | ulimit -d 8000000 -m 8000000 -v 8000000 | ||
128 | 7 | umask 002 | ||
129 | 8 | |||
130 | 9 | |||
131 | 10 | OPTIONS="$@" | ||
132 | 11 | qoption () { | ||
133 | 12 | for a in $OPTIONS; do if [ "$a" = "$1" ]; then return 0; fi; done | ||
134 | 13 | return 1 | ||
135 | 14 | } | ||
136 | 15 | |||
137 | 16 | option () { | ||
138 | 17 | for a in $OPTIONS; do if [ "$a" = "$1" ]; then date -uR; return 0; fi; done | ||
139 | 18 | return 1 | ||
140 | 19 | } | ||
141 | 20 | |||
142 | 21 | LP_SERVICE="${LP_SERVICE:-production}" | ||
143 | 22 | DISTRIBUTION="${DISTRIBUTION:-ubuntu}" | ||
144 | 23 | DEFAULT_SERIES=wily | ||
145 | 24 | SERIES="${SERIES:-$DEFAULT_SERIES}" | ||
146 | 25 | |||
147 | 26 | # DATE | ||
148 | 27 | NOW=`date +"%F/%T" -u` | ||
149 | 28 | |||
150 | 29 | # Dirs: | ||
151 | 30 | BASE=/home/ubuntu-archive/proposed-migration | ||
152 | 31 | DAK_LOCKDIR=/srv/ftp-master.debian.org/lock | ||
153 | 32 | FTP_MIRROR=/home/ubuntu-archive/mirror/$DISTRIBUTION | ||
154 | 33 | |||
155 | 34 | D_I=$BASE/d-i | ||
156 | 35 | VAR=$BASE/var | ||
157 | 36 | SSH=$BASE/ssh | ||
158 | 37 | HEIDI=$BASE/Heidi | ||
159 | 38 | INPUT=$BASE/input | ||
160 | 39 | CODE=$BASE/code/b1 | ||
161 | 40 | |||
162 | 41 | DATA=$VAR/data | ||
163 | 42 | LOCKDIR=$VAR/lock | ||
164 | 43 | HEIDI_SET=$HEIDI/set | ||
165 | 44 | SCRIPTS=$CODE/scripts | ||
166 | 45 | FAUXDIR=$CODE/fauxpkg | ||
167 | 46 | UPDATE_OUT=$CODE/update_out | ||
168 | 47 | URGENCIES=$INPUT/urgencies | ||
169 | 48 | |||
170 | 49 | LOCK=$LOCKDIR/britney-$DISTRIBUTION-$SERIES.lock | ||
171 | 50 | DAK_LOCK=$DAK_LOCKDIR/daily.lock | ||
172 | 51 | DAK_STOP=$DAK_LOCKDIR/archive.stop | ||
173 | 52 | |||
174 | 53 | TESTING=$DATA/$SERIES | ||
175 | 54 | UNSTABLE=$DATA/$SERIES-proposed | ||
176 | 55 | TPU=$DATA/testing-proposed-updates | ||
177 | 56 | |||
178 | 57 | FAUXPKG_SCRIPT=$FAUXDIR/fauxpkg.py | ||
179 | 58 | SSH_KEY=$SSH/ftp-master_trigger_key | ||
180 | 59 | |||
181 | 60 | HTML=/home/ubuntu-archive/public_html/proposed-migration | ||
182 | 61 | if [ "$DISTRIBUTION" != ubuntu ]; then | ||
183 | 62 | HTML="$HTML/$DISTRIBUTION" | ||
184 | 63 | fi | ||
185 | 64 | BOOTSTRAP_DIR=/home/ubuntu-archive/public_html/bootstrap | ||
186 | 65 | |||
187 | 66 | # Britney 2 | ||
188 | 67 | DATA_B2=$VAR/data-b2 | ||
189 | 68 | CODE_B2=$BASE/code/b2 | ||
190 | 69 | B2_OUTPUT=$DATA_B2/output | ||
191 | 70 | B2_CONFIG=${B2_CONFIG:-$CODE_B2/britney.conf} | ||
192 | 71 | B2_CONFIG_NOBREAKALL=${B2_CONFIG_NOBREAKALL:-$CODE_B2/britney_nobreakall.conf} | ||
193 | 72 | |||
194 | 73 | if [ -f $DAK_STOP ]; then | ||
195 | 74 | echo "$DAK_STOP exists, not running" | ||
196 | 75 | exit 1 | ||
197 | 76 | fi | ||
198 | 77 | |||
199 | 78 | # 10800 seconds = 3 hours | ||
200 | 79 | # 129600 seconds = 36 hours | ||
201 | 80 | if ! lockfile -r0 -l129600 $LOCK 2>/dev/null >/dev/null; then | ||
202 | 81 | echo "Could not get britney lockfile!" | ||
203 | 82 | ls -l "$LOCK" | ||
204 | 83 | exit 1 | ||
205 | 84 | fi | ||
206 | 85 | |||
207 | 86 | trap exit_function 0 | ||
208 | 87 | exit_function () { | ||
209 | 88 | rm -f $LOCK | ||
210 | 89 | } | ||
211 | 90 | |||
212 | 91 | #eval $( dak admin config db-shell ) | ||
213 | 92 | |||
214 | 93 | suite_info () { | ||
215 | 94 | python -c ' | ||
216 | 95 | from __future__ import print_function | ||
217 | 96 | |||
218 | 97 | import os | ||
219 | 98 | import sys | ||
220 | 99 | |||
221 | 100 | from launchpadlib.launchpad import Launchpad as _Launchpad | ||
222 | 101 | |||
223 | 102 | # Work around non-multiple-instance-safety of launchpadlib (bug #459418). | ||
224 | 103 | class Launchpad(_Launchpad): | ||
225 | 104 | @classmethod | ||
226 | 105 | def _get_paths(cls, service_root, launchpadlib_dir=None): | ||
227 | 106 | service_root, launchpadlib_dir, cache_path, service_root_dir = ( | ||
228 | 107 | _Launchpad._get_paths( | ||
229 | 108 | service_root, launchpadlib_dir=launchpadlib_dir)) | ||
230 | 109 | cache_path += "-proposed-migration" | ||
231 | 110 | if not os.path.exists(cache_path): | ||
232 | 111 | os.makedirs(cache_path, 0o700) | ||
233 | 112 | return service_root, launchpadlib_dir, cache_path, service_root_dir | ||
234 | 113 | |||
235 | 114 | launchpad = Launchpad.login_anonymously("proposed-migration", sys.argv[1]) | ||
236 | 115 | distro = launchpad.distributions[sys.argv[2]] | ||
237 | 116 | series_name = sys.argv[3].split("-")[0] | ||
238 | 117 | series = distro.getSeries(name_or_version=series_name) | ||
239 | 118 | '"$1" "$LP_SERVICE" "$DISTRIBUTION" "$2" | ||
240 | 119 | } | ||
241 | 120 | |||
242 | 121 | suite_arches () { | ||
243 | 122 | suite_info 'print(" ".join(arch.architecture_tag for arch in series.architectures))' "$1" | ||
244 | 123 | } | ||
245 | 124 | |||
246 | 125 | suite_archindep () { | ||
247 | 126 | suite_info 'print(series.nominatedarchindep.architecture_tag)' "$1" | ||
248 | 127 | } | ||
249 | 128 | |||
250 | 129 | if ! qoption allowdaklock; then | ||
251 | 130 | while [ -f $DAK_LOCK ]; do | ||
252 | 131 | echo `date` $DAK_LOCK exists. Sleeping in 10 more minutes. | ||
253 | 132 | sleep 600 | ||
254 | 133 | done | ||
255 | 134 | fi | ||
256 | 135 | |||
257 | 136 | urgencies () { | ||
258 | 137 | echo URGENCIES: | ||
259 | 138 | cd $BASE | ||
260 | 139 | for u in $URGENCIES/install-urgencies-*; do | ||
261 | 140 | [ -e "$u" ] || continue | ||
262 | 141 | cat "$u" >> $1/$SERIES/Urgency # XXX I'd rather not have this in $DATA --dato | ||
263 | 142 | rm "$u" | ||
264 | 143 | done | ||
265 | 144 | } | ||
266 | 145 | |||
267 | 146 | if option urgencies; then | ||
268 | 147 | urgencies $DATA_B2 | ||
269 | 148 | fi | ||
270 | 149 | |||
271 | 150 | bugs () { | ||
272 | 151 | for suite in $SERIES $SERIES-proposed; do | ||
273 | 152 | x="$1/${suite}/BugsV" | ||
274 | 153 | wget --quiet -O "${x}.new" http://bugs.debian.org/release-critical/britney/${suite}-nr | ||
275 | 154 | if [ -s ${x}.new ]; then mv ${x}.new $x; else rm $x.new; exit 1; fi | ||
276 | 155 | done | ||
277 | 156 | } | ||
278 | 157 | if option bugs; then | ||
279 | 158 | echo BUGS: | ||
280 | 159 | bugs $DATA_B2 | ||
281 | 160 | fi | ||
282 | 161 | |||
283 | 162 | if option bugs_b1; then | ||
284 | 163 | echo BUGS_B1: | ||
285 | 164 | bugs $DATA | ||
286 | 165 | fi | ||
287 | 166 | |||
288 | 167 | if option bugs_b2; then | ||
289 | 168 | echo BUGS_B2: | ||
290 | 169 | bugs $DATA_B2 | ||
291 | 170 | fi | ||
292 | 171 | |||
293 | 172 | blocks () { | ||
294 | 173 | local tags | ||
295 | 174 | [ "$DISTRIBUTION" = ubuntu ] || return 0 | ||
296 | 175 | mkdir -p "$1/$SERIES-proposed" | ||
297 | 176 | if [ "$SERIES" = "$DEFAULT_SERIES" ]; then | ||
298 | 177 | tags="block-proposed block-proposed-$SERIES" | ||
299 | 178 | else | ||
300 | 179 | tags="block-proposed-$SERIES" | ||
301 | 180 | fi | ||
302 | 181 | python -c ' | ||
303 | 182 | from __future__ import print_function | ||
304 | 183 | |||
305 | 184 | import calendar | ||
306 | 185 | import os | ||
307 | 186 | import sys | ||
308 | 187 | try: | ||
309 | 188 | from urllib.parse import urlsplit | ||
310 | 189 | except ImportError: | ||
311 | 190 | from urlparse import urlsplit | ||
312 | 191 | |||
313 | 192 | from launchpadlib.launchpad import Launchpad as _Launchpad | ||
314 | 193 | |||
315 | 194 | # Work around non-multiple-instance-safety of launchpadlib (bug #459418). | ||
316 | 195 | class Launchpad(_Launchpad): | ||
317 | 196 | @classmethod | ||
318 | 197 | def _get_paths(cls, service_root, launchpadlib_dir=None): | ||
319 | 198 | service_root, launchpadlib_dir, cache_path, service_root_dir = ( | ||
320 | 199 | _Launchpad._get_paths( | ||
321 | 200 | service_root, launchpadlib_dir=launchpadlib_dir)) | ||
322 | 201 | cache_path += "-proposed-migration" | ||
323 | 202 | if not os.path.exists(cache_path): | ||
324 | 203 | os.makedirs(cache_path, 0o700) | ||
325 | 204 | return service_root, launchpadlib_dir, cache_path, service_root_dir | ||
326 | 205 | |||
327 | 206 | launchpad = Launchpad.login_with("proposed-migration", sys.argv[1]) | ||
328 | 207 | distro = launchpad.distributions[sys.argv[2]] | ||
329 | 208 | tags = sys.argv[3].split() | ||
330 | 209 | for task in distro.searchTasks(omit_targeted=False, tags=tags): | ||
331 | 210 | target = task.target | ||
332 | 211 | bug = task.bug | ||
333 | 212 | if urlsplit(target.resource_type_link).fragment in ( | ||
334 | 213 | "distribution_source_package", "source_package"): | ||
335 | 214 | for action in reversed( | ||
336 | 215 | [a for a in bug.activity if a.whatchanged == "tags"]): | ||
337 | 216 | oldtags = action.oldvalue.split() | ||
338 | 217 | newtags = action.newvalue.split() | ||
339 | 218 | gained_block = False | ||
340 | 219 | for tag in tags: | ||
341 | 220 | if tag not in oldtags and tag in newtags: | ||
342 | 221 | gained_block = True | ||
343 | 222 | break | ||
344 | 223 | if gained_block: | ||
345 | 224 | date = action.datechanged | ||
346 | 225 | break | ||
347 | 226 | else: | ||
348 | 227 | date = bug.date_created | ||
349 | 228 | print("%s %d %d" % | ||
350 | 229 | (os.path.basename(target.self_link), bug.id, | ||
351 | 230 | calendar.timegm(date.timetuple()))) | ||
352 | 231 | ' "$LP_SERVICE" "$DISTRIBUTION" "$tags" >"$1/$SERIES-proposed/Blocks.new" | ||
353 | 232 | mv "$1/$SERIES-proposed/Blocks.new" "$1/$SERIES-proposed/Blocks" | ||
354 | 233 | } | ||
355 | 234 | if option blocks; then | ||
356 | 235 | echo BLOCKS: | ||
357 | 236 | blocks $DATA_B2 | ||
358 | 237 | fi | ||
359 | 238 | |||
360 | 239 | pkg_lists () { | ||
361 | 240 | for suite in $SERIES $SERIES-proposed; do | ||
362 | 241 | mkdir -p $1/$suite | ||
363 | 242 | suite_dirs=$FTP_MIRROR/dists/$suite | ||
364 | 243 | if [ "$suite" = "$SERIES" ]; then | ||
365 | 244 | suite_dirs="$suite_dirs $FTP_MIRROR/dists/$SERIES-updates" | ||
366 | 245 | fi | ||
367 | 246 | >$1/$suite/Sources | ||
368 | 247 | for suite_dir in $suite_dirs; do | ||
369 | 248 | gzip -t $suite_dir/{main,restricted,universe,multiverse}/source/Sources.gz | ||
370 | 249 | zcat $suite_dir/{main,restricted,universe,multiverse}/source/Sources.gz >>$1/$suite/Sources | ||
371 | 250 | done | ||
372 | 251 | for arch in `suite_arches $suite`; do | ||
373 | 252 | >$1/$suite/Packages_$arch | ||
374 | 253 | for suite_dir in $suite_dirs; do | ||
375 | 254 | gzip -t $suite_dir/{main,restricted,universe,multiverse}/binary-$arch/Packages.gz | ||
376 | 255 | zcat $suite_dir/{main,restricted,universe,multiverse}/binary-$arch/Packages.gz >>$1/$suite/Packages_$arch | ||
377 | 256 | gzip -t $suite_dir/{main,restricted,universe,multiverse}/debian-installer/binary-$arch/Packages.gz | ||
378 | 257 | zcat $suite_dir/{main,restricted,universe,multiverse}/debian-installer/binary-$arch/Packages.gz >>$1/$suite/Packages_$arch | ||
379 | 258 | done | ||
380 | 259 | done | ||
381 | 260 | done | ||
382 | 261 | $FAUXPKG_SCRIPT generate $1/$SERIES $1/$SERIES-proposed | ||
383 | 262 | } | ||
384 | 263 | |||
385 | 264 | lite_sync () { | ||
386 | 265 | cat <<EOF | rsync -a --files-from=- $1 $2 | ||
387 | 266 | $SERIES/Dates | ||
388 | 267 | $SERIES/BugsV | ||
389 | 268 | $SERIES/Urgency | ||
390 | 269 | $SERIES-proposed/BugsV | ||
391 | 270 | $SERIES-proposed/Hints | ||
392 | 271 | EOF | ||
393 | 272 | |||
394 | 273 | } | ||
395 | 274 | |||
396 | 275 | if option pkglists; then | ||
397 | 276 | echo PKGLISTS: | ||
398 | 277 | cd $DATA_B2 | ||
399 | 278 | pkg_lists $DATA_B2 | ||
400 | 279 | fi | ||
401 | 280 | |||
402 | 281 | if option sync_b2; then | ||
403 | 282 | rsync -ar $DATA/ $DATA_B2 | ||
404 | 283 | fi | ||
405 | 284 | |||
406 | 285 | # Give options to run a b2 from scratch after b1 has finished | ||
407 | 286 | if option pkglists_b2; then | ||
408 | 287 | echo PKGLISTS_B2: | ||
409 | 288 | cd $DATA_B2 | ||
410 | 289 | pkg_lists $DATA_B2 | ||
411 | 290 | fi | ||
412 | 291 | |||
413 | 292 | if option pkglists_b1; then | ||
414 | 293 | echo PKGLISTS_B1: | ||
415 | 294 | cd $DATA | ||
416 | 295 | pkg_lists $DATA | ||
417 | 296 | fi | ||
418 | 297 | |||
419 | 298 | if option sync_b2_lite; then | ||
420 | 299 | lite_sync $DATA $DATA_B2 | ||
421 | 300 | fi | ||
422 | 301 | |||
423 | 302 | if option sync_b1; then | ||
424 | 303 | rsync -ar $DATA_B2/ $DATA | ||
425 | 304 | fi | ||
426 | 305 | |||
427 | 306 | if option sync_b1_lite; then | ||
428 | 307 | lite_sync $DATA_B2 $DATA | ||
429 | 308 | fi | ||
430 | 309 | |||
431 | 310 | make_hints_branch () { | ||
432 | 311 | if [ -d "$2" ]; then | ||
433 | 312 | bzr pull -q -d "$2" --remember --overwrite "$1" | ||
434 | 313 | else | ||
435 | 314 | bzr branch "$1" "$2" | ||
436 | 315 | fi | ||
437 | 316 | } | ||
438 | 317 | |||
439 | 318 | if option hints_bzr; then | ||
440 | 319 | echo HINTS_BZR: | ||
441 | 320 | if [ "$DISTRIBUTION" = ubuntu ]; then | ||
442 | 321 | if [ "$SERIES" = "$DEFAULT_SERIES" ]; then | ||
443 | 322 | branch="lp:~ubuntu-release/britney/hints-ubuntu" | ||
444 | 323 | else | ||
445 | 324 | branch="lp:~ubuntu-sru/britney/hints-ubuntu-$SERIES" | ||
446 | 325 | fi | ||
447 | 326 | make_hints_branch "$DATA_B2/$SERIES-proposed/Hints" "$branch" | ||
448 | 327 | if [ "$SERIES" = "$DEFAULT_SERIES" ]; then | ||
449 | 328 | make_hints_branch \ | ||
450 | 329 | "$DATA_B2/$SERIES-proposed/Hints/ubuntu-touch" \ | ||
451 | 330 | "lp:~ubuntu-touch-release/britney/hints-ubuntu-touch" | ||
452 | 331 | else | ||
453 | 332 | rm -rf "$DATA_B2/$SERIES-proposed/Hints/ubuntu-touch" | ||
454 | 333 | fi | ||
455 | 334 | elif [ "$DISTRIBUTION" = ubuntu-rtm ]; then | ||
456 | 335 | make_hints_branch \ | ||
457 | 336 | "$DATA_B2/$SERIES-proposed/Hints" \ | ||
458 | 337 | lp:~ubuntu-release/britney/hints-ubuntu-rtm | ||
459 | 338 | fi | ||
460 | 339 | fi | ||
461 | 340 | |||
462 | 341 | run_b1 () { | ||
463 | 342 | cd $UPDATE_OUT | ||
464 | 343 | ./update_out.py $TESTING $UNSTABLE $TPU | ||
465 | 344 | } | ||
466 | 345 | |||
467 | 346 | b2_diff () { | ||
468 | 347 | tmp_dir=`mktemp -d` | ||
469 | 348 | master="b2" | ||
470 | 349 | [ "$master" = "b1" ] && secondary="b2" || secondary="b1" | ||
471 | 350 | (cd $tmp_dir | ||
472 | 351 | |||
473 | 352 | sort $TESTING/HeidiResult >HeidiResult_b1 | ||
474 | 353 | sort $B2_OUTPUT/$SERIES/HeidiResult >HeidiResult_b2 | ||
475 | 354 | |||
476 | 355 | sed -e '/^<p>Generated: /d' $CODE/update_out/update.EXCUSES_py >excuses_b1.html | ||
477 | 356 | sed -e '/^<p>Generated: /d' $B2_OUTPUT/$SERIES/excuses.html >excuses_b2.html | ||
478 | 357 | |||
479 | 358 | touch -m -r $TESTING/HeidiResult HeidiResult_b1 | ||
480 | 359 | touch -m -r $B2_OUTPUT/$SERIES/HeidiResult HeidiResult_b2 | ||
481 | 360 | |||
482 | 361 | touch -m -r $CODE/update_out/update.EXCUSES_py excuses_b1.html | ||
483 | 362 | touch -m -r $B2_OUTPUT/$SERIES/excuses.html excuses_b2.html | ||
484 | 363 | |||
485 | 364 | # NB: If you remove the "head" below, add a "|| true"; otherwise | ||
486 | 365 | # set -e may not allow the HeidiResult diff to execute. | ||
487 | 366 | diff -u excuses_${master}.html excuses_${secondary}.html | head -n 1000 | ||
488 | 367 | diff -u HeidiResult_${master} HeidiResult_${secondary} | head -n 1000) | ||
489 | 368 | rm -rf $tmp_dir | ||
490 | 369 | } | ||
491 | 370 | |||
492 | 371 | b2_diff_with_mail () { | ||
493 | 372 | b2_diff | ||
494 | 373 | b2_diff | ifne mail -s "britney2 diff `date -u +'%Y-%m-%d %H:%M'`" \ | ||
495 | 374 | -a "Reply-To: britney2@release.debian.org" britney2@release.debian.org | ||
496 | 375 | } | ||
497 | 376 | |||
498 | 377 | make_b2_config () { | ||
499 | 378 | local arches archindep | ||
500 | 379 | arches=`suite_arches $SERIES` | ||
501 | 380 | archindep=`suite_archindep $SERIES` | ||
502 | 381 | sed -e "s/^\\(ARCHITECTURES *= \\).*/\\1$arches/" \ | ||
503 | 382 | -e "s/^\\(NOBREAKALL_ARCHES *= \\).*/\\1$archindep/" \ | ||
504 | 383 | "$1" >"$2" | ||
505 | 384 | } | ||
506 | 385 | |||
507 | 386 | run_b2 () { | ||
508 | 387 | cd $BASE | ||
509 | 388 | make_b2_config "$B2_CONFIG" "$B2_CONFIG.$DISTRIBUTION.$SERIES" | ||
510 | 389 | $CODE_B2/britney.py -c "$B2_CONFIG.$DISTRIBUTION.$SERIES" -v --distribution=$DISTRIBUTION --series=$SERIES | ||
511 | 390 | } | ||
512 | 391 | |||
513 | 392 | if option run; then | ||
514 | 393 | echo RUN: | ||
515 | 394 | run_b2 | ||
516 | 395 | fi | ||
517 | 396 | |||
518 | 397 | if option run_b1; then | ||
519 | 398 | echo RUN_B1: | ||
520 | 399 | run_b1 | ||
521 | 400 | # assume that this will have been run after a "run" which is b2 | ||
522 | 401 | b2_diff_with_mail | ||
523 | 402 | fi | ||
524 | 403 | |||
525 | 404 | if option run_b2; then | ||
526 | 405 | echo RUN_B2: | ||
527 | 406 | run_b2 | ||
528 | 407 | b2_diff_with_mail | ||
529 | 408 | fi | ||
530 | 409 | |||
531 | 410 | if option b2_diff; then | ||
532 | 411 | b2_diff | ||
533 | 412 | fi | ||
534 | 413 | |||
535 | 414 | lp_import() { | ||
536 | 415 | # tell LP about the new delta | ||
537 | 416 | promote-to-release -l "$LP_SERVICE" -d "$DISTRIBUTION" -s "$SERIES" -v "$1" | ||
538 | 417 | } | ||
539 | 418 | |||
540 | 419 | save () { | ||
541 | 420 | cd $BASE | ||
542 | 421 | echo RESULTS: | ||
543 | 422 | # process a delta | ||
544 | 423 | if [ "$1" = "b1" ]; then | ||
545 | 424 | DELTA="$TESTING/HeidiResultDelta" | ||
546 | 425 | else | ||
547 | 426 | DELTA="$B2_OUTPUT/$SERIES/HeidiResultDelta" | ||
548 | 427 | fi | ||
549 | 428 | echo Using data from $DELTA | ||
550 | 429 | lp_import "$DELTA" | ||
551 | 430 | printf " done\n" | ||
552 | 431 | } | ||
553 | 432 | |||
554 | 433 | if option save_b1; then | ||
555 | 434 | save b1 | ||
556 | 435 | fi | ||
557 | 436 | if option save || option save_b2; then | ||
558 | 437 | save b2 | ||
559 | 438 | fi | ||
560 | 439 | |||
561 | 440 | create_uninst_report () { | ||
562 | 441 | $CODE_B2/britney.py -c $1 --distribution=$DISTRIBUTION --series=$SERIES --print-uninst >$HTML/$2.new | ||
563 | 442 | echo -e "\n# Generated: `date -uR`" >>$HTML/$2.new | ||
564 | 443 | mv $HTML/$2.new $HTML/$2 | ||
565 | 444 | } | ||
566 | 445 | |||
567 | 446 | create_ood_report () { | ||
568 | 447 | $SCRIPTS/ood_report.py $1 >$HTML/$2.new | ||
569 | 448 | echo -e "\n# Generated: `date -uR`" >>$HTML/$2.new | ||
570 | 449 | mv $HTML/$2.new $HTML/$2 | ||
571 | 450 | } | ||
572 | 451 | |||
573 | 452 | stats () { | ||
574 | 453 | echo STATS: | ||
575 | 454 | mkdir -p "$HTML/$SERIES" | ||
576 | 455 | if [ "$1" = "b1" ]; then | ||
577 | 456 | cp $UPDATE_OUT/update.EXCUSES_py $HTML/$SERIES/update_excuses.html | ||
578 | 457 | cp $UPDATE_OUT/update.OUTPUT_py $HTML/$SERIES/update_output.txt | ||
579 | 458 | else | ||
580 | 459 | cp $DATA_B2/output/$SERIES/excuses.html $HTML/$SERIES/update_excuses.html | ||
581 | 460 | cp $DATA_B2/output/$SERIES/excuses.yaml $HTML/$SERIES/update_excuses.yaml | ||
582 | 461 | cp $DATA_B2/output/$SERIES/output.txt $HTML/$SERIES/update_output.txt | ||
583 | 462 | cp $DATA_B2/$SERIES-proposed/Blocks $HTML/$SERIES/blocks.txt | ||
584 | 463 | fi | ||
585 | 464 | #gzip -9 < $HTML/$SERIES/update_excuses.html > $HTML/$SERIES/update_excuses.html.gz | ||
586 | 465 | #gzip -9 < $HTML/$SERIES/update_output.txt > $HTML/$SERIES/update_output.txt.gz | ||
587 | 466 | mkdir -p "$HTML/update_output/$SERIES/${NOW%/*}" | ||
588 | 467 | mkdir -p "$HTML/update_excuses/$SERIES/${NOW%/*}" | ||
589 | 468 | gzip -9c $HTML/$SERIES/update_output.txt > $HTML/update_output/$SERIES/$NOW.txt.gz | ||
590 | 469 | gzip -9c $HTML/$SERIES/update_excuses.html > $HTML/update_excuses/$SERIES/$NOW.html.gz | ||
591 | 470 | gzip -9c $HTML/$SERIES/update_excuses.yaml > $HTML/update_excuses/$SERIES/$NOW.yaml.gz | ||
592 | 471 | |||
593 | 472 | # TODO: {stable,unstable}_uninst.txt -- needs support in b2, talk to Fabio | ||
594 | 473 | # TODO: this creates uninstallability reports against b2 results, not b1's | ||
595 | 474 | make_b2_config "$B2_CONFIG" "$B2_CONFIG.$DISTRIBUTION.$SERIES" | ||
596 | 475 | make_b2_config "$B2_CONFIG_NOBREAKALL" "$B2_CONFIG_NOBREAKALL.$DISTRIBUTION.$SERIES" | ||
597 | 476 | create_uninst_report "$B2_CONFIG.$DISTRIBUTION.$SERIES" ${SERIES}_uninst.txt | ||
598 | 477 | create_uninst_report "$B2_CONFIG_NOBREAKALL.$DISTRIBUTION.$SERIES" ${SERIES}_uninst_full.txt | ||
599 | 478 | |||
600 | 479 | #if grep -q -e '-meta-faux' $HTML/testing_uninst.txt; then | ||
601 | 480 | # echo >&2 'Warning! Some -meta-faux package is uninstallable!' | ||
602 | 481 | #fi | ||
603 | 482 | |||
604 | 483 | #create_ood_report $DATA_B2/stable stable_outdate.txt | ||
605 | 484 | #create_ood_report $DATA_B2/testing testing_outdate.txt | ||
606 | 485 | |||
607 | 486 | $SCRIPTS/backlog-report -o $HTML/$SERIES/update_excuses.csv $HTML/$SERIES/update_excuses.html | ||
608 | 487 | } | ||
609 | 488 | |||
610 | 489 | if option stats_b1; then | ||
611 | 490 | stats b1 | ||
612 | 491 | fi | ||
613 | 492 | if option stats || option stats_b2; then | ||
614 | 493 | stats b2 | ||
615 | 494 | fi | ||
616 | 495 | |||
617 | 496 | if option summary; then | ||
618 | 497 | cd $BASE | ||
619 | 498 | echo "Out of dates holding up testing:" | ||
620 | 499 | TERM=vt100 w3m -dump $HTML/$SERIES/update_excuses.html | sed -n 's/^ *[^ ] *[^ ]*out of date on \([^ ]*\): .*$/\1/p' | sort | uniq -c | sort -n | ||
621 | 500 | echo "Uninstallables holding up testing:" | ||
622 | 501 | sed < $HTML/$SERIES/update_excuses.html -n 's/^ *<li>[^ ]* (\([^, ]*\),.*) uninstallable.*$/\1/p' | sort | uniq -c | sort -n | ||
623 | 502 | #echo "wanna-build stats:" | ||
624 | 503 | #for a in alpha arm hppa hurd-i386 i386 ia64 m68k mips mipsel powerpc s390 sparc; do | ||
625 | 504 | # printf " %-12s " "$a:" | ||
626 | 505 | # /srv/wanna-build/bin/wanna-build-statistics --database=$a/build-db | | ||
627 | 506 | # grep "if also counting" || echo "-" | ||
628 | 507 | #done | ||
629 | 508 | fi | ||
630 | 509 | |||
631 | 510 | if option archivedata; then | ||
632 | 511 | echo ARCHIVE: | ||
633 | 512 | cd $VAR | ||
634 | 513 | tar czf data_bkup/data-$(date +"%Y.%m.%d").tgz data/{stable,testing,unstable,testing-proposed-updates} | ||
635 | 514 | fi | ||
636 | 515 | |||
637 | 516 | echo -n "Finished at: "; date -uR | ||
638 | 0 | 517 | ||
639 | === added directory 'fauxpkg' | |||
640 | === added file 'fauxpkg/FauxPackages' | |||
641 | --- fauxpkg/FauxPackages 1970-01-01 00:00:00 +0000 | |||
642 | +++ fauxpkg/FauxPackages 2015-06-09 16:34:27 +0000 | |||
643 | @@ -0,0 +1,59 @@ | |||
644 | 1 | Package: wine1.4-i386 | ||
645 | 2 | Source: wine1.6 | ||
646 | 3 | Version: ${unstable-version} | ||
647 | 4 | Architecture: amd64 | ||
648 | 5 | Provides: wine-i386 | ||
649 | 6 | Multi-Arch: foreign | ||
650 | 7 | |||
651 | 8 | Package: wine1.6-i386 | ||
652 | 9 | Source: wine1.6 | ||
653 | 10 | Version: ${unstable-version} | ||
654 | 11 | Architecture: amd64 | ||
655 | 12 | Provides: wine-i386 | ||
656 | 13 | Multi-Arch: foreign | ||
657 | 14 | |||
658 | 15 | Package: nspluginviewer | ||
659 | 16 | Source: nspluginwrapper | ||
660 | 17 | Version: ${unstable-version} | ||
661 | 18 | Architecture: amd64 arm64 armhf powerpc ppc64el | ||
662 | 19 | Multi-Arch: foreign | ||
663 | 20 | |||
664 | 21 | Package: ocaml-mingw-w64-x86-64 | ||
665 | 22 | Source: mingw-ocaml | ||
666 | 23 | Version: ${unstable-version} | ||
667 | 24 | Architecture: i386 | ||
668 | 25 | Multi-Arch: foreign | ||
669 | 26 | |||
670 | 27 | Package: claws-mail-extra-plugins-dbg | ||
671 | 28 | Version: 1:1 | ||
672 | 29 | |||
673 | 30 | Package: claws-mail-html2-viewer | ||
674 | 31 | Version: 1:1 | ||
675 | 32 | |||
676 | 33 | Package: ubuntu-emulator-images | ||
677 | 34 | Source: android | ||
678 | 35 | Version: ${unstable-version} | ||
679 | 36 | Architecture: amd64 armhf | ||
680 | 37 | Multi-Arch: foreign | ||
681 | 38 | |||
682 | 39 | Package: ubuntu-emulator-runtime | ||
683 | 40 | Source: android | ||
684 | 41 | Version: ${unstable-version} | ||
685 | 42 | Architecture: amd64 armhf | ||
686 | 43 | Multi-Arch: foreign | ||
687 | 44 | |||
688 | 45 | Package: libnss-mdns-i386 | ||
689 | 46 | Source: nss-mdns | ||
690 | 47 | Version: ${unstable-version} | ||
691 | 48 | Architecture: amd64 | ||
692 | 49 | Multi-Arch: foreign | ||
693 | 50 | |||
694 | 51 | Package: unity8 | ||
695 | 52 | Version: ${unstable-version} | ||
696 | 53 | Architecture: arm64 powerpc ppc64el | ||
697 | 54 | |||
698 | 55 | Package: liboxideqt-qmlplugin | ||
699 | 56 | Source: oxide-qt | ||
700 | 57 | Version: ${unstable-version} | ||
701 | 58 | Architecture: arm64 powerpc ppc64el | ||
702 | 59 | |||
703 | 0 | 60 | ||
704 | === added file 'fauxpkg/README' | |||
705 | --- fauxpkg/README 1970-01-01 00:00:00 +0000 | |||
706 | +++ fauxpkg/README 2015-06-09 16:34:27 +0000 | |||
707 | @@ -0,0 +1,50 @@ | |||
708 | 1 | Files and scripts in this directory are in charge on creating a list of | ||
709 | 2 | "faux" packages for britney. These are packages that do not exist in the | ||
710 | 3 | archive, but which we want britney to think they exist. At the moment | ||
711 | 4 | they are used for: | ||
712 | 5 | |||
713 | 6 | - allowing packages in contrib to migrate even if their dependencies | ||
714 | 7 | are not satisfied within the archive. This is done by creating a | ||
715 | 8 | faux package for each missing dependency. | ||
716 | 9 | |||
717 | 10 | - ensure some packages do not get accidentally removed, because they | ||
718 | 11 | are needed by parts of testing which don't declare a Depends on | ||
719 | 12 | them. In particular, to ensure packages needed by the installer and | ||
720 | 13 | tasksel are not removed. This is done by creating faux packages that | ||
721 | 14 | do depend on all packages which are not to be removed. | ||
722 | 15 | |||
723 | 16 | To create packages of the first kind, just append suitable entries to | ||
724 | 17 | the toplevel FauxPackages file. These should have at least a Package and | ||
725 | 18 | Version fields. You can restrict their existance to certain architectures | ||
726 | 19 | by providing an Architecture field with a list of architectures. Other | ||
727 | 20 | fields are propagated verbatim to britney, eg. Provides. | ||
728 | 21 | |||
729 | 22 | As for the second kind, you don't directly create faux packages, but | ||
730 | 23 | just append the packages which shouldn't be removed to the appropriate | ||
731 | 24 | file under the "noremove.d" directory. Those files just contain a list | ||
732 | 25 | of *binary* packages, one per line. A couple of important notes: | ||
733 | 26 | |||
734 | 27 | - if the binary package is not in testing, do not add it: wait until | ||
735 | 28 | it migrates. | ||
736 | 29 | |||
737 | 30 | - if the binary package is not available on i386 (being arch:all would | ||
738 | 31 | suffice), you have to qualify it with [arch], mentioning one arch in | ||
739 | 32 | which it is available. | ||
740 | 33 | |||
741 | 34 | - the names of the files under noremove.d must be valid as package | ||
742 | 35 | names, e.g. not contain underscores. | ||
743 | 36 | |||
744 | 37 | The noremove.d/tasksel file is special: it gets generated automatically | ||
745 | 38 | by the fauxpkg.py script, by running the script with the "update-tasksel" | ||
746 | 39 | command. (Currently is it to be run by hand whenever the tasksel | ||
747 | 40 | maintainer notices our file is out of date.) | ||
748 | 41 | |||
749 | 42 | One further caveat: if one of these faux meta-packages becomes uninstallable, | ||
750 | 43 | they stop working (since the removal of their dependencies does not increase | ||
751 | 44 | the uninstallability count). The britney script has a mechanism in place to | ||
752 | 45 | warn in case they become uninstallable. When adding packages to the lists, | ||
753 | 46 | make sure to watch the next britney mail, in case you added conflicting | ||
754 | 47 | packages. (In that case, you want to add such packages in different files | ||
755 | 48 | under noremove.d.) | ||
756 | 49 | |||
757 | 50 | Please don't forget to commit your changes to files in this directory! | ||
758 | 0 | 51 | ||
759 | === added file 'fauxpkg/fauxpkg.py' | |||
760 | --- fauxpkg/fauxpkg.py 1970-01-01 00:00:00 +0000 | |||
761 | +++ fauxpkg/fauxpkg.py 2015-06-09 16:34:27 +0000 | |||
762 | @@ -0,0 +1,181 @@ | |||
763 | 1 | #! /usr/bin/python | ||
764 | 2 | ## encoding: utf-8 | ||
765 | 3 | # | ||
766 | 4 | # Copyright (c) 2008 Adeodato Simó (dato@net.com.org.es) | ||
767 | 5 | # Licensed under the terms of the MIT license. | ||
768 | 6 | |||
769 | 7 | """Handle the creation of britney faux packages. | ||
770 | 8 | |||
771 | 9 | This program gets called from the "britney" script in order to append to the | ||
772 | 10 | Packages_<arch> files a list of faux packages. This is done with the "generate" | ||
773 | 11 | command, passing a list of britney suite directories: | ||
774 | 12 | |||
775 | 13 | % fauxpkg.py generate /home/release/britney/var/data/{testing,unstable} | ||
776 | 14 | |||
777 | 15 | This automatically appeds to the Packages files the list of faux packages. See | ||
778 | 16 | the README file in this directory for the input files from which such list is | ||
779 | 17 | generated. | ||
780 | 18 | """ | ||
781 | 19 | |||
782 | 20 | import os | ||
783 | 21 | import re | ||
784 | 22 | import sys | ||
785 | 23 | import glob | ||
786 | 24 | import tempfile | ||
787 | 25 | import subprocess | ||
788 | 26 | |||
789 | 27 | import apt_pkg | ||
790 | 28 | apt_pkg.init() | ||
791 | 29 | |||
792 | 30 | ## | ||
793 | 31 | |||
794 | 32 | BASEDIR = os.path.dirname(__file__) | ||
795 | 33 | |||
796 | 34 | NOREMOVE_DIR = os.path.join(BASEDIR, 'noremove.d') | ||
797 | 35 | FAUX_PACKAGES = os.path.join(BASEDIR, 'FauxPackages') | ||
798 | 36 | |||
799 | 37 | DEFAULT_NOREMOVE_ARCH = 'amd64' | ||
800 | 38 | |||
801 | 39 | ## | ||
802 | 40 | |||
803 | 41 | def main(): | ||
804 | 42 | if not sys.argv[1:]: | ||
805 | 43 | print >>sys.stderr, 'Usage: %s <generate | update-tasksel> [ britney_suite_dir1 ... ]' % ( | ||
806 | 44 | os.path.basename(sys.argv[0])) | ||
807 | 45 | sys.exit(1) | ||
808 | 46 | else: | ||
809 | 47 | command = sys.argv.pop(1) | ||
810 | 48 | |||
811 | 49 | if command == 'generate': | ||
812 | 50 | if not sys.argv[1:]: | ||
813 | 51 | print >>sys.stderr, 'E: need at least one britney suite directory' | ||
814 | 52 | sys.exit(1) | ||
815 | 53 | else: | ||
816 | 54 | do_generate(sys.argv[1:]) | ||
817 | 55 | elif command == 'update-tasksel': | ||
818 | 56 | if sys.argv[1:]: | ||
819 | 57 | print >>sys.stderr, 'E: extra arguments not allowed' | ||
820 | 58 | sys.exit(1) | ||
821 | 59 | else: | ||
822 | 60 | do_update_tasksel() | ||
823 | 61 | else: | ||
824 | 62 | print >>sys.stderr, 'E: unknown command %s' % (command,) | ||
825 | 63 | |||
826 | 64 | ## | ||
827 | 65 | |||
828 | 66 | def do_generate(directories): | ||
829 | 67 | arches = set() | ||
830 | 68 | allfaux = {} | ||
831 | 69 | |||
832 | 70 | for dir_ in directories: | ||
833 | 71 | arches.update([ re.sub(r'^.*/Packages_', '', x) | ||
834 | 72 | for x in glob.glob(os.path.join(dir_, 'Packages_*')) ]) | ||
835 | 73 | |||
836 | 74 | unstable_versions = {} | ||
837 | 75 | for dir_ in directories: | ||
838 | 76 | with open(os.path.join(dir_, 'Sources')) as f: | ||
839 | 77 | parser = apt_pkg.TagFile(f) | ||
840 | 78 | for section in parser: | ||
841 | 79 | if 'Package' in section and 'Version' in section: | ||
842 | 80 | unstable_versions[section['Package']] = section['Version'] | ||
843 | 81 | |||
844 | 82 | # First, FauxPackages | ||
845 | 83 | try: | ||
846 | 84 | parser = apt_pkg.TagFile(file(FAUX_PACKAGES)) | ||
847 | 85 | step = parser.step | ||
848 | 86 | section = parser.section | ||
849 | 87 | except AttributeError, e: | ||
850 | 88 | parser = apt_pkg.ParseTagFile(file(FAUX_PACKAGES)) | ||
851 | 89 | step = parser.Step | ||
852 | 90 | section = parser.Section | ||
853 | 91 | while step(): | ||
854 | 92 | d = dict(section) | ||
855 | 93 | d['Section'] = 'faux' # crucial; britney filters HeidiResult based on section | ||
856 | 94 | |||
857 | 95 | if not d.has_key('Architecture'): | ||
858 | 96 | these_arches = arches | ||
859 | 97 | else: | ||
860 | 98 | these_arches = set(re.split(r'[, ]+', d['Architecture'])) | ||
861 | 99 | |||
862 | 100 | d['Architecture'] = 'all' # same everywhere | ||
863 | 101 | |||
864 | 102 | if d.get('Version') == '${unstable-version}': | ||
865 | 103 | source = d.get('Source', d.get('Package')) | ||
866 | 104 | if source in unstable_versions: | ||
867 | 105 | d['Version'] = unstable_versions[source] | ||
868 | 106 | |||
869 | 107 | for arch in these_arches: | ||
870 | 108 | allfaux.setdefault(arch, []).append(d) | ||
871 | 109 | |||
872 | 110 | # Now, noremove.d | ||
873 | 111 | for f in glob.glob(os.path.join(NOREMOVE_DIR, '*.list')): | ||
874 | 112 | pkgs = {} | ||
875 | 113 | basename = re.sub(r'.+/(.+)\.list', r'\1', f) | ||
876 | 114 | |||
877 | 115 | for line in file(f): | ||
878 | 116 | line = line.strip() | ||
879 | 117 | if re.match(r'^#', line): | ||
880 | 118 | continue | ||
881 | 119 | elif re.match(r'\S+$', line): | ||
882 | 120 | pkg = line | ||
883 | 121 | arch = DEFAULT_NOREMOVE_ARCH | ||
884 | 122 | else: | ||
885 | 123 | m = re.match(r'(\S+)\s+\[(.+)\]', line) | ||
886 | 124 | if m: | ||
887 | 125 | pkg, arch = m.groups() | ||
888 | 126 | else: | ||
889 | 127 | print >>sys.stderr, 'W: could not parse line %r' % (line,) | ||
890 | 128 | |||
891 | 129 | arch = re.split(r'[, ]+', arch)[0] # just in case | ||
892 | 130 | pkgs.setdefault(arch, set()).add(pkg) | ||
893 | 131 | |||
894 | 132 | for arch in pkgs.keys(): | ||
895 | 133 | d = { 'Package': '%s-meta-faux' % (basename,), 'Version': '1', | ||
896 | 134 | 'Section': 'faux', 'Architecture': '%s' % (arch,), | ||
897 | 135 | 'Depends': ', '.join(pkgs[arch]) } | ||
898 | 136 | allfaux.setdefault(arch, []).append(d) | ||
899 | 137 | |||
900 | 138 | # Write the result | ||
901 | 139 | for arch in arches: | ||
902 | 140 | if arch not in allfaux: | ||
903 | 141 | continue | ||
904 | 142 | for dir_ in directories: | ||
905 | 143 | f = os.path.join(dir_, 'Packages_' + arch) | ||
906 | 144 | if not os.path.exists(f): | ||
907 | 145 | continue | ||
908 | 146 | else: | ||
909 | 147 | f = file(f, 'a') | ||
910 | 148 | for d in allfaux[arch]: | ||
911 | 149 | f.write('\n'.join('%s: %s' % (k, v) for k, v in d.iteritems()) + '\n\n') | ||
912 | 150 | |||
913 | 151 | ## | ||
914 | 152 | |||
915 | 153 | def do_update_tasksel(): | ||
916 | 154 | p = subprocess.Popen('dak ls -f control-suite -s unstable -a source tasksel', | ||
917 | 155 | shell=True, stdout=subprocess.PIPE) | ||
918 | 156 | p.wait() | ||
919 | 157 | version = p.stdout.readline().split()[1] | ||
920 | 158 | |||
921 | 159 | p = subprocess.Popen('dak ls -f control-suite -s unstable -S -a i386,all tasksel', | ||
922 | 160 | shell=True, stdout=subprocess.PIPE) | ||
923 | 161 | p.wait() | ||
924 | 162 | tasks = [] | ||
925 | 163 | |||
926 | 164 | for line in p.stdout: | ||
927 | 165 | pkg = line.split()[0] | ||
928 | 166 | |||
929 | 167 | if pkg.startswith('task-'): | ||
930 | 168 | tasks.append(pkg) | ||
931 | 169 | |||
932 | 170 | # Write the new file | ||
933 | 171 | tmpfd, tmpname = tempfile.mkstemp(dir=NOREMOVE_DIR) | ||
934 | 172 | os.write(tmpfd, '# Generated from tasksel-data %s\n' % (version,)) | ||
935 | 173 | os.write(tmpfd, '\n'.join(sorted(tasks)) + '\n') | ||
936 | 174 | os.close(tmpfd) | ||
937 | 175 | os.chmod(tmpname, 0644) | ||
938 | 176 | os.rename(tmpname, os.path.join(NOREMOVE_DIR, 'tasksel.list')) | ||
939 | 177 | |||
940 | 178 | ## | ||
941 | 179 | |||
942 | 180 | if __name__ == '__main__': | ||
943 | 181 | main() | ||
944 | 0 | 182 | ||
945 | === added directory 'fauxpkg/noremove.d' | |||
946 | === added file 'fauxpkg/noremove.d/README' | |||
947 | --- fauxpkg/noremove.d/README 1970-01-01 00:00:00 +0000 | |||
948 | +++ fauxpkg/noremove.d/README 2015-06-09 16:34:27 +0000 | |||
949 | @@ -0,0 +1,3 @@ | |||
950 | 1 | Packages listed in these files are protected against accidental removals | ||
951 | 2 | from testing. Please mail debian-release@lists.debian.org if you think | ||
952 | 3 | some package should be added to any of these lists. | ||
953 | 0 | 4 | ||
954 | === added directory 'scripts' | |||
955 | === added file 'scripts/backlog-report' | |||
956 | --- scripts/backlog-report 1970-01-01 00:00:00 +0000 | |||
957 | +++ scripts/backlog-report 2015-06-09 16:34:27 +0000 | |||
958 | @@ -0,0 +1,86 @@ | |||
959 | 1 | #! /usr/bin/python | ||
960 | 2 | # | ||
961 | 3 | # Generate a report of the backlog in -proposed. | ||
962 | 4 | |||
963 | 5 | from __future__ import print_function | ||
964 | 6 | |||
965 | 7 | __metaclass__ = type | ||
966 | 8 | |||
967 | 9 | import calendar | ||
968 | 10 | import csv | ||
969 | 11 | import gzip | ||
970 | 12 | import io | ||
971 | 13 | from optparse import OptionParser | ||
972 | 14 | import os | ||
973 | 15 | import re | ||
974 | 16 | import sys | ||
975 | 17 | import time | ||
976 | 18 | |||
977 | 19 | |||
978 | 20 | generated_re = re.compile(r"^<p>Generated: (.*)</p>$") | ||
979 | 21 | |||
980 | 22 | |||
981 | 23 | def import_excuses(csv_writer, path): | ||
982 | 24 | generated_time = None | ||
983 | 25 | valid_candidates = 0 | ||
984 | 26 | not_considered = 0 | ||
985 | 27 | |||
986 | 28 | if path.endswith(".gz"): | ||
987 | 29 | binary = gzip.open(path) | ||
988 | 30 | else: | ||
989 | 31 | binary = io.open(path, mode="rb") | ||
990 | 32 | try: | ||
991 | 33 | with io.BufferedReader(binary) as buffered: | ||
992 | 34 | with io.TextIOWrapper(buffered) as text: | ||
993 | 35 | for line in text: | ||
994 | 36 | match = generated_re.match(line) | ||
995 | 37 | if match: | ||
996 | 38 | generated_time = time.strptime( | ||
997 | 39 | match.group(1), "%Y.%m.%d %H:%M:%S +0000") | ||
998 | 40 | elif line.startswith("<li>Valid candidate"): | ||
999 | 41 | valid_candidates += 1 | ||
1000 | 42 | elif line.startswith("<li>Not considered"): | ||
1001 | 43 | not_considered += 1 | ||
1002 | 44 | finally: | ||
1003 | 45 | binary.close() | ||
1004 | 46 | |||
1005 | 47 | assert generated_time is not None | ||
1006 | 48 | |||
1007 | 49 | csv_writer.writerow({ | ||
1008 | 50 | "time": calendar.timegm(generated_time) * 1000, | ||
1009 | 51 | "valid candidates": valid_candidates, | ||
1010 | 52 | "not considered": not_considered, | ||
1011 | 53 | "total": valid_candidates + not_considered, | ||
1012 | 54 | }) | ||
1013 | 55 | |||
1014 | 56 | |||
1015 | 57 | def main(): | ||
1016 | 58 | parser = OptionParser(description="Generate a backlog report.") | ||
1017 | 59 | parser.add_option( | ||
1018 | 60 | "-o", "--output", help="Write output to this file (default: stdout).") | ||
1019 | 61 | options, args = parser.parse_args() | ||
1020 | 62 | |||
1021 | 63 | if options.output is not None: | ||
1022 | 64 | csv_is_new = not os.path.exists(options.output) | ||
1023 | 65 | if sys.version < "3": | ||
1024 | 66 | output = open(options.output, "ab") | ||
1025 | 67 | else: | ||
1026 | 68 | output = open(options.output, "a", newline="") | ||
1027 | 69 | else: | ||
1028 | 70 | csv_is_new = True | ||
1029 | 71 | output = sys.stdout | ||
1030 | 72 | |||
1031 | 73 | try: | ||
1032 | 74 | csv_writer = csv.DictWriter( | ||
1033 | 75 | output, ["time", "valid candidates", "not considered", "total"]) | ||
1034 | 76 | if csv_is_new: | ||
1035 | 77 | csv_writer.writeheader() | ||
1036 | 78 | for arg in args: | ||
1037 | 79 | import_excuses(csv_writer, arg) | ||
1038 | 80 | finally: | ||
1039 | 81 | if options.output is not None: | ||
1040 | 82 | output.close() | ||
1041 | 83 | |||
1042 | 84 | |||
1043 | 85 | if __name__ == "__main__": | ||
1044 | 86 | main() | ||
1045 | 0 | 87 | ||
1046 | === added file 'scripts/ood_report.py' | |||
1047 | --- scripts/ood_report.py 1970-01-01 00:00:00 +0000 | |||
1048 | +++ scripts/ood_report.py 2015-06-09 16:34:27 +0000 | |||
1049 | @@ -0,0 +1,101 @@ | |||
1050 | 1 | #! /usr/bin/python | ||
1051 | 2 | ## encoding: utf-8 | ||
1052 | 3 | # | ||
1053 | 4 | # Copyright (c) 2008 Adeodato Simó (dato@net.com.org.es) | ||
1054 | 5 | # Licensed under the terms of the MIT license. | ||
1055 | 6 | |||
1056 | 7 | """Create a report of packages that are out-of-date in each architecture. | ||
1057 | 8 | |||
1058 | 9 | It expects a single "directory" argument, that should be a britney directory | ||
1059 | 10 | for a distribution, i.e. containing Packages_<arch> files and Sources. | ||
1060 | 11 | """ | ||
1061 | 12 | |||
1062 | 13 | import os | ||
1063 | 14 | import re | ||
1064 | 15 | import sys | ||
1065 | 16 | import glob | ||
1066 | 17 | |||
1067 | 18 | import apt_pkg | ||
1068 | 19 | apt_pkg.init() | ||
1069 | 20 | |||
1070 | 21 | ## | ||
1071 | 22 | |||
1072 | 23 | def main(): | ||
1073 | 24 | if len(sys.argv) != 2: | ||
1074 | 25 | print >>sys.stderr, 'Usage: %s <directory>' | ||
1075 | 26 | sys.exit(1) | ||
1076 | 27 | else: | ||
1077 | 28 | directory = sys.argv[1] | ||
1078 | 29 | |||
1079 | 30 | pkgfiles = glob.glob(os.path.join(directory, 'Packages_*')) | ||
1080 | 31 | versions = get_src_versions(os.path.join(directory, 'Sources')) | ||
1081 | 32 | |||
1082 | 33 | ood = {} # { arch1: { srcpk1: (oldver, [binpkg1, binpkg2, ...]), ... }, ... } | ||
1083 | 34 | |||
1084 | 35 | for pkgfile in pkgfiles: | ||
1085 | 36 | arch = re.sub(r'^.*/Packages_', '', pkgfile) | ||
1086 | 37 | try: | ||
1087 | 38 | parser = apt_pkg.TagFile(file(pkgfile)) | ||
1088 | 39 | step = parser.step | ||
1089 | 40 | get_section = parser.section | ||
1090 | 41 | get_field = parser.section.get | ||
1091 | 42 | except AttributeError, e: | ||
1092 | 43 | parser = apt_pkg.ParseTagFile(file(pkgfile)) | ||
1093 | 44 | step = parser.Step | ||
1094 | 45 | get_section = parser.Section | ||
1095 | 46 | get_field = parser.Section.get | ||
1096 | 47 | d = ood[arch] = {} | ||
1097 | 48 | |||
1098 | 49 | while step(): | ||
1099 | 50 | pkg = get_section['Package'] | ||
1100 | 51 | src = get_field('Source') or pkg | ||
1101 | 52 | |||
1102 | 53 | if ' ' in src: | ||
1103 | 54 | m = re.match(r'(\S+) \((\S+)\)$', src) | ||
1104 | 55 | src = m.group(1) | ||
1105 | 56 | ver = m.group(2) | ||
1106 | 57 | else: | ||
1107 | 58 | ver = re.sub(r'\+b\d+$', '', get_section['Version']) | ||
1108 | 59 | |||
1109 | 60 | try: | ||
1110 | 61 | distver = versions[src] | ||
1111 | 62 | except KeyError: | ||
1112 | 63 | pass # faux package | ||
1113 | 64 | else: | ||
1114 | 65 | if ver != distver: | ||
1115 | 66 | d.setdefault(src, (ver, []))[1].append(pkg) | ||
1116 | 67 | |||
1117 | 68 | arches = sorted(ood.keys()) | ||
1118 | 69 | |||
1119 | 70 | for arch in arches: | ||
1120 | 71 | print '* %s' % (arch,) | ||
1121 | 72 | for src, (oldver, binpkgs) in sorted(ood[arch].iteritems()): | ||
1122 | 73 | # do not print binpkgs, I think it clutters the view too much | ||
1123 | 74 | print ' %s (%s)' % (src, oldver) | ||
1124 | 75 | |||
1125 | 76 | |||
1126 | 77 | print '* summary' | ||
1127 | 78 | print '\n'.join(map(lambda x: '%4d %s' % (len(ood[x]), x), arches)) | ||
1128 | 79 | |||
1129 | 80 | ## | ||
1130 | 81 | |||
1131 | 82 | def get_src_versions(sources_file): | ||
1132 | 83 | """Return a dict { srcname: version, ... }.""" | ||
1133 | 84 | mydict = {} | ||
1134 | 85 | try: | ||
1135 | 86 | parser = apt_pkg.TagFile(file(sources_file)) | ||
1136 | 87 | |||
1137 | 88 | while parser.step(): | ||
1138 | 89 | mydict[parser.section['Package']] = parser.section['Version'] | ||
1139 | 90 | except AttributeError, e: | ||
1140 | 91 | parser = apt_pkg.ParseTagFile(file(sources_file)) | ||
1141 | 92 | |||
1142 | 93 | while parser.Step(): | ||
1143 | 94 | mydict[parser.Section['Package']] = parser.Section['Version'] | ||
1144 | 95 | |||
1145 | 96 | return mydict | ||
1146 | 97 | |||
1147 | 98 | ## | ||
1148 | 99 | |||
1149 | 100 | if __name__ == '__main__': | ||
1150 | 101 | main() | ||
1151 | 0 | 102 | ||
1152 | === added file 'scripts/udeb-report' | |||
1153 | --- scripts/udeb-report 1970-01-01 00:00:00 +0000 | |||
1154 | +++ scripts/udeb-report 2015-06-09 16:34:27 +0000 | |||
1155 | @@ -0,0 +1,49 @@ | |||
1156 | 1 | #!/bin/sh | ||
1157 | 2 | |||
1158 | 3 | # Generate a report with out-of-date udebs. Queries come from the | ||
1159 | 4 | # original "d-i" script by Jeroen van Wolffelaar. Modified not to emit | ||
1160 | 5 | # output for queries that return 0 rows by Adeodato Simó. | ||
1161 | 6 | |||
1162 | 7 | # TODO(dato): rewrite these queries. | ||
1163 | 8 | |||
1164 | 9 | export PAGER="cat" | ||
1165 | 10 | |||
1166 | 11 | eval $(dak admin config db-shell) | ||
1167 | 12 | |||
1168 | 13 | ## | ||
1169 | 14 | |||
1170 | 15 | maybe_print () { | ||
1171 | 16 | if ! echo "$2" | grep -q -E '^\(0 rows\)$'; then | ||
1172 | 17 | echo "$1" | ||
1173 | 18 | echo "$2" | ||
1174 | 19 | echo | ||
1175 | 20 | fi | ||
1176 | 21 | } | ||
1177 | 22 | |||
1178 | 23 | maybe_print "udeb's in testing that don't (anymore) correspond to any testing source:" \ | ||
1179 | 24 | "`psql -c \"select b.package, b.version, (SELECT arch_string from | ||
1180 | 25 | architecture where b.architecture=architecture.id) as arch, s.source from | ||
1181 | 26 | bin_associations ba LEFT JOIN binaries b on (ba.bin=b.id) LEFT JOIN source s | ||
1182 | 27 | on (b.source=s.id) WHERE ba.suite=4 AND s.id NOT IN (SELECT source from | ||
1183 | 28 | src_associations WHERE suite=4) AND b.type = 'udeb' ORDER BY s.source, | ||
1184 | 29 | b.package, b.architecture;\"`" | ||
1185 | 30 | |||
1186 | 31 | maybe_print "udeb's in unstable that should be in testing too:" \ | ||
1187 | 32 | "`psql -c \"select b.package, b.version, (SELECT arch_string from | ||
1188 | 33 | architecture where b.architecture=architecture.id) as arch, s.source from | ||
1189 | 34 | bin_associations ba LEFT JOIN binaries b on (ba.bin=b.id) LEFT JOIN source s | ||
1190 | 35 | on (b.source=s.id) WHERE ba.suite=5 AND NOT EXISTS (SELECT 1 FROM | ||
1191 | 36 | bin_associations ba2 WHERE ba2.suite=4 AND ba2.bin=ba.bin) AND s.id IN (SELECT | ||
1192 | 37 | source from src_associations WHERE suite=4) AND b.type = 'udeb' AND | ||
1193 | 38 | b.architecture IN (SELECT architecture from suite_architectures where suite = 4) | ||
1194 | 39 | ORDER BY s.source, b.package, b.architecture;\"`" | ||
1195 | 40 | |||
1196 | 41 | maybe_print "udeb's in t-p-u that should be in testing too:" \ | ||
1197 | 42 | "`psql -c \"select b.package, b.version, (SELECT arch_string from | ||
1198 | 43 | architecture where b.architecture=architecture.id) as arch, s.source from | ||
1199 | 44 | bin_associations ba LEFT JOIN binaries b on (ba.bin=b.id) LEFT JOIN source s | ||
1200 | 45 | on (b.source=s.id) WHERE ba.suite=3 AND NOT EXISTS (SELECT 1 FROM | ||
1201 | 46 | bin_associations ba2 WHERE ba2.suite=4 AND ba2.bin=ba.bin) AND s.id IN (SELECT | ||
1202 | 47 | source from src_associations WHERE suite=4) AND b.type = 'udeb' AND | ||
1203 | 48 | b.architecture IN (SELECT architecture from suite_architectures where suite = 4) | ||
1204 | 49 | ORDER BY s.source, b.package, b.architecture;\"`" | ||
1205 | 0 | 50 | ||
1206 | === added directory 'update_out' | |||
1207 | === added file 'update_out/.gitignore' | |||
1208 | --- update_out/.gitignore 1970-01-01 00:00:00 +0000 | |||
1209 | +++ update_out/.gitignore 2015-06-09 16:34:27 +0000 | |||
1210 | @@ -0,0 +1,6 @@ | |||
1211 | 1 | *.o | ||
1212 | 2 | *.so | ||
1213 | 3 | /oldstuff | ||
1214 | 4 | /Makefile.dep | ||
1215 | 5 | /update.EXCUSES_py | ||
1216 | 6 | /update.OUTPUT_py | ||
1217 | 0 | 7 | ||
1218 | === added file 'update_out/Makefile' | |||
1219 | --- update_out/Makefile 1970-01-01 00:00:00 +0000 | |||
1220 | +++ update_out/Makefile 2015-06-09 16:34:27 +0000 | |||
1221 | @@ -0,0 +1,33 @@ | |||
1222 | 1 | |||
1223 | 2 | CC = gcc | ||
1224 | 3 | CXX = g++ | ||
1225 | 4 | CFLAGS = -fPIC -Wall -W -O2 -DNDEBUG -DMDEBUG0 -g -p # -DDIAGNOSE | ||
1226 | 5 | CXXFLAGS = $(CFLAGS) | ||
1227 | 6 | |||
1228 | 7 | all : britneymodule.so # libajdpkg.a aptvercmp checklib freelist | ||
1229 | 8 | |||
1230 | 9 | clean : | ||
1231 | 10 | rm -f *.so *.o *~ Makefile.dep gmon.out | ||
1232 | 11 | rm -f freelist aptvercmp checklib libajdpkg.a | ||
1233 | 12 | |||
1234 | 13 | checklib : checklib.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o | ||
1235 | 14 | $(CC) $(CFLAGS) -o checklib $^ -lapt-pkg # -lccmalloc -ldl | ||
1236 | 15 | |||
1237 | 16 | aptvercmp : dpkg-lib.cpp | ||
1238 | 17 | $(CXX) $(CFLAGS) -DTESTBIN -o aptvercmp dpkg-lib.cpp -lapt-pkg | ||
1239 | 18 | |||
1240 | 19 | freelist : freelist.c assert.o | ||
1241 | 20 | $(CC) $(CFLAGS) -DTESTBIN -o $@ $^ | ||
1242 | 21 | |||
1243 | 22 | #libajdpkg.a : dpkg.o dpkg-lib.o memory3.o freelist.o assert.o | ||
1244 | 23 | # ar rv $@ $^ | ||
1245 | 24 | # ranlib $@ | ||
1246 | 25 | |||
1247 | 26 | britneymodule.so : britney-py.o dpkg.o dpkg-lib.o memory3.o freelist.o assert.o | ||
1248 | 27 | $(CXX) -shared -o britneymodule.so $^ -lapt-pkg | ||
1249 | 28 | |||
1250 | 29 | Makefile.dep : | ||
1251 | 30 | @gcc -MM *.c *.cpp > Makefile.dep | ||
1252 | 31 | @echo Makefile.dep : Makefile *.c *.h >> Makefile.dep | ||
1253 | 32 | |||
1254 | 33 | -include Makefile.dep | ||
1255 | 0 | 34 | ||
1256 | === added file 'update_out/README' | |||
1257 | --- update_out/README 1970-01-01 00:00:00 +0000 | |||
1258 | +++ update_out/README 2015-06-09 16:34:27 +0000 | |||
1259 | @@ -0,0 +1,32 @@ | |||
1260 | 1 | |||
1261 | 2 | BUILDING | ||
1262 | 3 | ======== | ||
1263 | 4 | |||
1264 | 5 | Install libapt-pkg-dev | ||
1265 | 6 | |||
1266 | 7 | testing/ $ make | ||
1267 | 8 | testing/ $ mkdir old cur out | ||
1268 | 9 | testing/ $ cd testing | ||
1269 | 10 | testing/testing/ $ perl Makefile.PL | ||
1270 | 11 | testing/testing/ $ make | ||
1271 | 12 | |||
1272 | 13 | Add old and new packages files into old and cur, respectively. | ||
1273 | 14 | |||
1274 | 15 | testing/ $ ./checklib i386 alpha | ||
1275 | 16 | |||
1276 | 17 | Will generate some test stuff in out/ | ||
1277 | 18 | |||
1278 | 19 | TODO | ||
1279 | 20 | ==== | ||
1280 | 21 | |||
1281 | 22 | Need some way of actually updating archives. | ||
1282 | 23 | Need some way of judging differences between Packages files. | ||
1283 | 24 | (so I can see what hasn't been updated and work out why; | ||
1284 | 25 | so I can check that Packages.gz matches dpkg-scanpackages output) | ||
1285 | 26 | Need some way of automatically explaining why packages aren't upgraded. | ||
1286 | 27 | (shouldn't be hard?) | ||
1287 | 28 | |||
1288 | 29 | BUGS | ||
1289 | 30 | ==== | ||
1290 | 31 | |||
1291 | 32 | out/ directory must exist for checklib, or segfault | ||
1292 | 0 | 33 | ||
1293 | === added file 'update_out/assert.c' | |||
1294 | --- update_out/assert.c 1970-01-01 00:00:00 +0000 | |||
1295 | +++ update_out/assert.c 2015-06-09 16:34:27 +0000 | |||
1296 | @@ -0,0 +1,11 @@ | |||
1297 | 1 | #include <stdio.h> | ||
1298 | 2 | #include <stdlib.h> | ||
1299 | 3 | |||
1300 | 4 | int _myassertbug(int line, char *file, char *err) { | ||
1301 | 5 | fprintf(stderr, "Assertion failed: %s:%d: %s\n", file, line, err); | ||
1302 | 6 | fprintf(stderr, "I HATE YOU!!!"); | ||
1303 | 7 | ((void(*)())0)(); | ||
1304 | 8 | abort(); | ||
1305 | 9 | return 0; | ||
1306 | 10 | } | ||
1307 | 11 | |||
1308 | 0 | 12 | ||
1309 | === added file 'update_out/britney-py.c' | |||
1310 | --- update_out/britney-py.c 1970-01-01 00:00:00 +0000 | |||
1311 | +++ update_out/britney-py.c 2015-06-09 16:34:27 +0000 | |||
1312 | @@ -0,0 +1,871 @@ | |||
1313 | 1 | #include <python2.7/Python.h> | ||
1314 | 2 | |||
1315 | 3 | #include "dpkg.h" | ||
1316 | 4 | |||
1317 | 5 | #define MAKE_PY_LIST(L,S,E,I,V) \ | ||
1318 | 6 | do { \ | ||
1319 | 7 | L = PyList_New(0); \ | ||
1320 | 8 | if (!L) break; \ | ||
1321 | 9 | for (S; E; I) { \ | ||
1322 | 10 | PyObject *EL; \ | ||
1323 | 11 | EL = Py_BuildValue V; \ | ||
1324 | 12 | if (!EL) { \ | ||
1325 | 13 | Py_DECREF(L); \ | ||
1326 | 14 | L = NULL; \ | ||
1327 | 15 | break; \ | ||
1328 | 16 | } \ | ||
1329 | 17 | PyList_Append(L, EL); \ | ||
1330 | 18 | Py_DECREF(EL); \ | ||
1331 | 19 | } \ | ||
1332 | 20 | if (L) PyList_Sort(L); \ | ||
1333 | 21 | } while(0) | ||
1334 | 22 | |||
1335 | 23 | /************************************************************************** | ||
1336 | 24 | * britney.Packages -- dpkg_packages wrapper | ||
1337 | 25 | *******************************************/ | ||
1338 | 26 | |||
1339 | 27 | typedef enum { DONTFREE, FREE } dpkgpackages_freeme; | ||
1340 | 28 | typedef struct { | ||
1341 | 29 | PyObject_HEAD | ||
1342 | 30 | dpkg_packages *pkgs; | ||
1343 | 31 | PyObject *ref; /* object packages are "in" */ | ||
1344 | 32 | dpkgpackages_freeme freeme; /* free pkgs when deallocing? */ | ||
1345 | 33 | } dpkgpackages; | ||
1346 | 34 | |||
1347 | 35 | staticforward PyTypeObject Packages_Type; | ||
1348 | 36 | |||
1349 | 37 | static PyObject *dpkgpackages_new(dpkg_packages *pkgs, | ||
1350 | 38 | dpkgpackages_freeme freeme, PyObject *ref) | ||
1351 | 39 | { | ||
1352 | 40 | dpkgpackages *res; | ||
1353 | 41 | |||
1354 | 42 | res = PyObject_NEW(dpkgpackages, &Packages_Type); | ||
1355 | 43 | if (res == NULL) return NULL; | ||
1356 | 44 | |||
1357 | 45 | res->pkgs = pkgs; | ||
1358 | 46 | res->ref = ref; Py_INCREF(res->ref); | ||
1359 | 47 | res->freeme = freeme; | ||
1360 | 48 | |||
1361 | 49 | return (PyObject *) res; | ||
1362 | 50 | } | ||
1363 | 51 | |||
1364 | 52 | static void dpkgpackages_dealloc(dpkgpackages *self) { | ||
1365 | 53 | if (self->freeme == FREE) free_packages(self->pkgs); | ||
1366 | 54 | Py_XDECREF(self->ref); | ||
1367 | 55 | self->pkgs = NULL; | ||
1368 | 56 | self->ref = NULL; | ||
1369 | 57 | PyObject_DEL(self); | ||
1370 | 58 | } | ||
1371 | 59 | |||
1372 | 60 | |||
1373 | 61 | static dpkg_collected_package *dpkgpackages_lookuppkg(dpkgpackages *self, | ||
1374 | 62 | char *pkgname) | ||
1375 | 63 | { | ||
1376 | 64 | dpkg_collected_package *cpkg = NULL; | ||
1377 | 65 | cpkg = lookup_packagetbl(self->pkgs->packages, pkgname); | ||
1378 | 66 | if (!cpkg) { | ||
1379 | 67 | PyErr_SetString(PyExc_ValueError, "Not a valid package"); | ||
1380 | 68 | } | ||
1381 | 69 | return cpkg; | ||
1382 | 70 | } | ||
1383 | 71 | |||
1384 | 72 | static PyObject *dpkgpackages_ispresent(dpkgpackages *self, PyObject *args) { | ||
1385 | 73 | dpkg_collected_package *cpkg; | ||
1386 | 74 | char *pkgname; | ||
1387 | 75 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1388 | 76 | cpkg = lookup_packagetbl(self->pkgs->packages, pkgname); | ||
1389 | 77 | return cpkg ? Py_BuildValue("i", 1) : Py_BuildValue("i", 0); | ||
1390 | 78 | } | ||
1391 | 79 | |||
1392 | 80 | static PyObject *dpkgpackages_getversion(dpkgpackages *self, PyObject *args) { | ||
1393 | 81 | dpkg_collected_package *cpkg; | ||
1394 | 82 | char *pkgname; | ||
1395 | 83 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1396 | 84 | cpkg = lookup_packagetbl(self->pkgs->packages, pkgname); | ||
1397 | 85 | if (cpkg) return Py_BuildValue("s", cpkg->pkg->version); | ||
1398 | 86 | else return Py_BuildValue(""); | ||
1399 | 87 | } | ||
1400 | 88 | static PyObject *dpkgpackages_getsource(dpkgpackages *self, PyObject *args) { | ||
1401 | 89 | dpkg_collected_package *cpkg; | ||
1402 | 90 | char *pkgname; | ||
1403 | 91 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1404 | 92 | cpkg = lookup_packagetbl(self->pkgs->packages, pkgname); | ||
1405 | 93 | if (cpkg) return Py_BuildValue("s", cpkg->pkg->source); | ||
1406 | 94 | else return Py_BuildValue(""); | ||
1407 | 95 | } | ||
1408 | 96 | static PyObject *dpkgpackages_getsourcever(dpkgpackages *self, PyObject *args) { | ||
1409 | 97 | dpkg_collected_package *cpkg; | ||
1410 | 98 | char *pkgname; | ||
1411 | 99 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1412 | 100 | cpkg = lookup_packagetbl(self->pkgs->packages, pkgname); | ||
1413 | 101 | if (cpkg) return Py_BuildValue("s", cpkg->pkg->source_ver); | ||
1414 | 102 | else return Py_BuildValue(""); | ||
1415 | 103 | } | ||
1416 | 104 | static PyObject *dpkgpackages_isarchall(dpkgpackages *self, PyObject *args) { | ||
1417 | 105 | dpkg_collected_package *cpkg; | ||
1418 | 106 | char *pkgname; | ||
1419 | 107 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1420 | 108 | cpkg = lookup_packagetbl(self->pkgs->packages, pkgname); | ||
1421 | 109 | if (cpkg) return Py_BuildValue("i", cpkg->pkg->arch_all); | ||
1422 | 110 | else return Py_BuildValue(""); | ||
1423 | 111 | } | ||
1424 | 112 | static PyObject *dpkgpackages_isntarchall(dpkgpackages *self, PyObject *args) { | ||
1425 | 113 | dpkg_collected_package *cpkg; | ||
1426 | 114 | char *pkgname; | ||
1427 | 115 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1428 | 116 | cpkg = lookup_packagetbl(self->pkgs->packages, pkgname); | ||
1429 | 117 | if (cpkg) return Py_BuildValue("i", !cpkg->pkg->arch_all); | ||
1430 | 118 | else return Py_BuildValue(""); | ||
1431 | 119 | } | ||
1432 | 120 | static PyObject *dpkgpackages_getfield(dpkgpackages *self, PyObject *args) { | ||
1433 | 121 | char *field; | ||
1434 | 122 | char *pkgname; | ||
1435 | 123 | int i; | ||
1436 | 124 | dpkg_collected_package *cpkg; | ||
1437 | 125 | dpkg_paragraph *para; | ||
1438 | 126 | if (!PyArg_ParseTuple(args, "ss", &pkgname, &field)) return NULL; | ||
1439 | 127 | cpkg = dpkgpackages_lookuppkg(self, pkgname); | ||
1440 | 128 | if (!cpkg) return NULL; | ||
1441 | 129 | para = cpkg->pkg->details; | ||
1442 | 130 | for (i = 0; i < para->n_entries; i++) { | ||
1443 | 131 | if (strcasecmp(para->entry[i].name, field) == 0) { | ||
1444 | 132 | return Py_BuildValue("s", para->entry[i].value); | ||
1445 | 133 | } | ||
1446 | 134 | } | ||
1447 | 135 | return Py_BuildValue(""); | ||
1448 | 136 | } | ||
1449 | 137 | static PyObject *dpkgpackages_isinstallable(dpkgpackages *self, PyObject *args) | ||
1450 | 138 | { | ||
1451 | 139 | char *pkgname; | ||
1452 | 140 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1453 | 141 | if (checkinstallable2(self->pkgs, pkgname)) { | ||
1454 | 142 | return Py_BuildValue("i", 1); | ||
1455 | 143 | } else { | ||
1456 | 144 | return Py_BuildValue(""); | ||
1457 | 145 | } | ||
1458 | 146 | } | ||
1459 | 147 | static PyObject *dpkgpackages_isuninstallable(dpkgpackages *self, | ||
1460 | 148 | PyObject *args) | ||
1461 | 149 | { | ||
1462 | 150 | char *pkgname; | ||
1463 | 151 | if (!PyArg_ParseTuple(args, "s", &pkgname)) return NULL; | ||
1464 | 152 | if (!checkinstallable2(self->pkgs, pkgname)) { | ||
1465 | 153 | return Py_BuildValue("i", 1); | ||
1466 | 154 | } else { | ||
1467 | 155 | return Py_BuildValue(""); | ||
1468 | 156 | } | ||
1469 | 157 | } | ||
1470 | 158 | static PyObject *dpkgpackages_unsatdeps(dpkgpackages *self, PyObject *args) { | ||
1471 | 159 | /* arguments are: | ||
1472 | 160 | * testingpkgs[arch].unsatisfiable_deps(unstablepkgs[arch], "netbase", "Depends") | ||
1473 | 161 | * exciting, huh? | ||
1474 | 162 | */ | ||
1475 | 163 | |||
1476 | 164 | dpkgpackages *pkgpkgs; | ||
1477 | 165 | char *pkgname, *fieldname; | ||
1478 | 166 | dpkg_collected_package *cpkg; | ||
1479 | 167 | int fieldidx; | ||
1480 | 168 | int buflen = 100; | ||
1481 | 169 | char *buf = malloc(buflen); | ||
1482 | 170 | const char *fields[] = { "Pre-Depends", "Depends", "Recommends", | ||
1483 | 171 | "Suggests", NULL }; | ||
1484 | 172 | satisfieddeplist *unsatdeps, *dl; | ||
1485 | 173 | PyObject *res = Py_BuildValue("[]"); | ||
1486 | 174 | |||
1487 | 175 | if (!PyArg_ParseTuple(args, "O!ss", &Packages_Type, &pkgpkgs, &pkgname, &fieldname)) return NULL; | ||
1488 | 176 | |||
1489 | 177 | cpkg = lookup_packagetbl(pkgpkgs->pkgs->packages, pkgname); | ||
1490 | 178 | if (!cpkg) { | ||
1491 | 179 | PyErr_SetString(PyExc_ValueError, "Not a valid package"); | ||
1492 | 180 | return NULL; | ||
1493 | 181 | } | ||
1494 | 182 | |||
1495 | 183 | for (fieldidx = 0; fields[fieldidx]; fieldidx++) { | ||
1496 | 184 | if (strcmp(fields[fieldidx], fieldname) == 0) break; | ||
1497 | 185 | } | ||
1498 | 186 | if (!fields[fieldidx]) { | ||
1499 | 187 | PyErr_SetString(PyExc_ValueError, "Not a valid dependency field"); | ||
1500 | 188 | return NULL; | ||
1501 | 189 | } | ||
1502 | 190 | |||
1503 | 191 | unsatdeps = checkunsatisfiabledeps(self->pkgs, | ||
1504 | 192 | cpkg->pkg->depends[fieldidx]); | ||
1505 | 193 | for (dl = unsatdeps; dl != NULL; dl = dl->next) { | ||
1506 | 194 | int len; | ||
1507 | 195 | packagelist *it; | ||
1508 | 196 | PyObject *pkglist; | ||
1509 | 197 | deplist *depl; | ||
1510 | 198 | dependency *dep; | ||
1511 | 199 | |||
1512 | 200 | len = 0; | ||
1513 | 201 | buf[0] = '\0'; | ||
1514 | 202 | for (depl = dl->value->depl; depl; depl = depl->next) { | ||
1515 | 203 | dep = depl->value; | ||
1516 | 204 | len += strlen(dep->package) + 4; | ||
1517 | 205 | /* 4 = strlen(" | ") + 1 */ | ||
1518 | 206 | if (dep->op != dr_NOOP) { | ||
1519 | 207 | len += strlen(dep->version) + 6; | ||
1520 | 208 | /* 6 = strlen(" (>= )") */ | ||
1521 | 209 | } | ||
1522 | 210 | if (len >= buflen) { | ||
1523 | 211 | char *newbuf; | ||
1524 | 212 | newbuf = realloc(buf, len + 100); | ||
1525 | 213 | if (newbuf == NULL) { | ||
1526 | 214 | free_satisfieddeplist(unsatdeps); | ||
1527 | 215 | free(buf); | ||
1528 | 216 | Py_DECREF(res); | ||
1529 | 217 | PyErr_SetFromErrno(PyExc_MemoryError); | ||
1530 | 218 | return NULL; | ||
1531 | 219 | } | ||
1532 | 220 | buf = newbuf; | ||
1533 | 221 | buflen = len + 100; | ||
1534 | 222 | } | ||
1535 | 223 | if (buf[0] != '\0') strcat(buf, " | "); | ||
1536 | 224 | strcat(buf, dep->package); | ||
1537 | 225 | if (dep->op != dr_NOOP) { | ||
1538 | 226 | sprintf(buf + strlen(buf), " (%s %s)", | ||
1539 | 227 | dependency_relation_sym[dep->op], | ||
1540 | 228 | dep->version); | ||
1541 | 229 | } | ||
1542 | 230 | } | ||
1543 | 231 | |||
1544 | 232 | MAKE_PY_LIST(pkglist, it = dl->value->pkgs, it, it = it->next, | ||
1545 | 233 | ("s", it->value->package) | ||
1546 | 234 | ); | ||
1547 | 235 | |||
1548 | 236 | { | ||
1549 | 237 | PyObject *depel = Py_BuildValue("(sN)", buf, pkglist); | ||
1550 | 238 | PyList_Append(res, depel); | ||
1551 | 239 | Py_DECREF(depel); | ||
1552 | 240 | } | ||
1553 | 241 | } | ||
1554 | 242 | |||
1555 | 243 | free_satisfieddeplist(unsatdeps); | ||
1556 | 244 | free(buf); | ||
1557 | 245 | |||
1558 | 246 | return res; | ||
1559 | 247 | } | ||
1560 | 248 | |||
1561 | 249 | static PyObject *dpkgpackages_getattr(dpkgpackages *self, char *name) { | ||
1562 | 250 | static struct PyMethodDef dpkgsources_methods[] = { | ||
1563 | 251 | { "is_present", (binaryfunc) dpkgpackages_ispresent, | ||
1564 | 252 | METH_VARARGS, NULL }, | ||
1565 | 253 | { "get_version", (binaryfunc) dpkgpackages_getversion, | ||
1566 | 254 | METH_VARARGS, NULL }, | ||
1567 | 255 | { "get_source", (binaryfunc) dpkgpackages_getsource, | ||
1568 | 256 | METH_VARARGS, NULL }, | ||
1569 | 257 | { "get_sourcever", (binaryfunc) dpkgpackages_getsourcever, | ||
1570 | 258 | METH_VARARGS, NULL }, | ||
1571 | 259 | { "is_arch_all", (binaryfunc) dpkgpackages_isarchall, | ||
1572 | 260 | METH_VARARGS, NULL }, | ||
1573 | 261 | { "isnt_arch_all", (binaryfunc) dpkgpackages_isntarchall, | ||
1574 | 262 | METH_VARARGS, NULL }, | ||
1575 | 263 | { "get_field", (binaryfunc) dpkgpackages_getfield, | ||
1576 | 264 | METH_VARARGS, NULL }, | ||
1577 | 265 | { "is_installable", (binaryfunc) dpkgpackages_isinstallable, | ||
1578 | 266 | METH_VARARGS, NULL }, | ||
1579 | 267 | { "is_uninstallable", (binaryfunc)dpkgpackages_isuninstallable, | ||
1580 | 268 | METH_VARARGS, NULL }, | ||
1581 | 269 | { "unsatisfiable_deps", (binaryfunc) dpkgpackages_unsatdeps, | ||
1582 | 270 | METH_VARARGS, NULL }, | ||
1583 | 271 | { NULL, NULL, 0, NULL } | ||
1584 | 272 | }; | ||
1585 | 273 | |||
1586 | 274 | if (strcmp(name, "packages") == 0) { | ||
1587 | 275 | PyObject *packages; | ||
1588 | 276 | packagetbl_iter it; | ||
1589 | 277 | MAKE_PY_LIST(packages, | ||
1590 | 278 | it = first_packagetbl(self->pkgs->packages), | ||
1591 | 279 | !done_packagetbl(it), it = next_packagetbl(it), | ||
1592 | 280 | ("s", it.k) | ||
1593 | 281 | ); | ||
1594 | 282 | return packages; | ||
1595 | 283 | } | ||
1596 | 284 | |||
1597 | 285 | return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name); | ||
1598 | 286 | } | ||
1599 | 287 | |||
1600 | 288 | static PyTypeObject Packages_Type = { | ||
1601 | 289 | PyObject_HEAD_INIT(&PyType_Type) | ||
1602 | 290 | |||
1603 | 291 | 0, /* ob_size (0) */ | ||
1604 | 292 | "Packages", /* type name */ | ||
1605 | 293 | sizeof(dpkgpackages), /* basicsize */ | ||
1606 | 294 | 0, /* itemsize (0) */ | ||
1607 | 295 | |||
1608 | 296 | (destructor) dpkgpackages_dealloc, | ||
1609 | 297 | (printfunc) 0, | ||
1610 | 298 | (getattrfunc) dpkgpackages_getattr, | ||
1611 | 299 | (setattrfunc) 0, | ||
1612 | 300 | (cmpfunc) 0, | ||
1613 | 301 | (reprfunc) 0, | ||
1614 | 302 | |||
1615 | 303 | 0, /* number methods */ | ||
1616 | 304 | 0, /* sequence methods */ | ||
1617 | 305 | 0, /* mapping methods */ | ||
1618 | 306 | |||
1619 | 307 | (hashfunc) 0, /* dict[x] ?? */ | ||
1620 | 308 | (ternaryfunc) 0, /* x() */ | ||
1621 | 309 | (reprfunc) 0 /* str(x) */ | ||
1622 | 310 | }; | ||
1623 | 311 | |||
1624 | 312 | /************************************************************************** | ||
1625 | 313 | * britney.Sources -- dpkg_sources wrapper | ||
1626 | 314 | *****************************************/ | ||
1627 | 315 | |||
1628 | 316 | typedef struct { | ||
1629 | 317 | PyObject_HEAD | ||
1630 | 318 | dpkg_sources *srcs; | ||
1631 | 319 | } dpkgsources; | ||
1632 | 320 | |||
1633 | 321 | staticforward PyTypeObject Sources_Type; | ||
1634 | 322 | |||
1635 | 323 | static PyObject *dpkgsources_new(PyObject *self, PyObject *args) { | ||
1636 | 324 | dpkgsources *res = NULL; | ||
1637 | 325 | char *dir; | ||
1638 | 326 | PyObject *arches; | ||
1639 | 327 | char **archesStr = NULL; | ||
1640 | 328 | int i, count; | ||
1641 | 329 | |||
1642 | 330 | (void)self; /* unused */ | ||
1643 | 331 | |||
1644 | 332 | if (!PyArg_ParseTuple(args, "sO!", &dir, &PyList_Type, &arches)) { | ||
1645 | 333 | goto end; | ||
1646 | 334 | } | ||
1647 | 335 | |||
1648 | 336 | count = PyList_Size(arches); | ||
1649 | 337 | if (count <= 0) { | ||
1650 | 338 | PyErr_SetString(PyExc_TypeError, "No architectures specified"); | ||
1651 | 339 | goto end; | ||
1652 | 340 | } | ||
1653 | 341 | |||
1654 | 342 | archesStr = malloc(sizeof(char *) * count); | ||
1655 | 343 | if (!archesStr) { | ||
1656 | 344 | PyErr_SetFromErrno(PyExc_MemoryError); | ||
1657 | 345 | goto end; | ||
1658 | 346 | } | ||
1659 | 347 | |||
1660 | 348 | for (i = 0; i < count; i++) { | ||
1661 | 349 | PyObject *arch = PyList_GetItem(arches, i); | ||
1662 | 350 | if (!PyString_Check(arch)) { | ||
1663 | 351 | goto end; | ||
1664 | 352 | } | ||
1665 | 353 | archesStr[i] = PyString_AsString(arch); | ||
1666 | 354 | } | ||
1667 | 355 | |||
1668 | 356 | res = PyObject_NEW(dpkgsources, &Sources_Type); | ||
1669 | 357 | if (res == NULL) goto end; | ||
1670 | 358 | |||
1671 | 359 | res->srcs = read_directory(dir, count, archesStr); | ||
1672 | 360 | if (!res->srcs) { | ||
1673 | 361 | Py_DECREF(res); | ||
1674 | 362 | res = NULL; | ||
1675 | 363 | goto end; | ||
1676 | 364 | } | ||
1677 | 365 | |||
1678 | 366 | end: | ||
1679 | 367 | if (archesStr) free(archesStr); | ||
1680 | 368 | return (PyObject *) res; | ||
1681 | 369 | } | ||
1682 | 370 | |||
1683 | 371 | static void dpkgsources_dealloc(dpkgsources *self) { | ||
1684 | 372 | free_sources(self->srcs); | ||
1685 | 373 | self->srcs = NULL; | ||
1686 | 374 | PyObject_DEL(self); | ||
1687 | 375 | } | ||
1688 | 376 | |||
1689 | 377 | static PyObject *dpkgsources_packages(dpkgsources *self, PyObject *args) | ||
1690 | 378 | { | ||
1691 | 379 | char *arch; | ||
1692 | 380 | dpkg_packages *pkgs; | ||
1693 | 381 | if (!PyArg_ParseTuple(args, "s", &arch)) return NULL; | ||
1694 | 382 | pkgs = get_architecture(self->srcs, arch); | ||
1695 | 383 | return dpkgpackages_new(pkgs, FREE, (PyObject *) self); | ||
1696 | 384 | } | ||
1697 | 385 | |||
1698 | 386 | static PyObject *dpkgsources_isfake(dpkgsources *self, PyObject *args) { | ||
1699 | 387 | char *srcname; | ||
1700 | 388 | dpkg_source *src; | ||
1701 | 389 | |||
1702 | 390 | if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL; | ||
1703 | 391 | src = lookup_sourcetbl(self->srcs->sources, srcname); | ||
1704 | 392 | if (src) return Py_BuildValue("i", src->fake); | ||
1705 | 393 | else return Py_BuildValue(""); | ||
1706 | 394 | } | ||
1707 | 395 | |||
1708 | 396 | static PyObject *dpkgsources_getversion(dpkgsources *self, PyObject *args) { | ||
1709 | 397 | char *srcname; | ||
1710 | 398 | dpkg_source *src; | ||
1711 | 399 | |||
1712 | 400 | if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL; | ||
1713 | 401 | src = lookup_sourcetbl(self->srcs->sources, srcname); | ||
1714 | 402 | if (src) return Py_BuildValue("s", src->version); | ||
1715 | 403 | else return Py_BuildValue(""); | ||
1716 | 404 | } | ||
1717 | 405 | |||
1718 | 406 | static PyObject *dpkgsources_getfield(dpkgsources *self, PyObject *args) { | ||
1719 | 407 | char *srcname, *field; | ||
1720 | 408 | dpkg_source *src; | ||
1721 | 409 | int i; | ||
1722 | 410 | dpkg_paragraph *para; | ||
1723 | 411 | |||
1724 | 412 | if (!PyArg_ParseTuple(args, "ss", &srcname, &field)) return NULL; | ||
1725 | 413 | src = lookup_sourcetbl(self->srcs->sources, srcname); | ||
1726 | 414 | if (!src) { | ||
1727 | 415 | PyErr_SetString(PyExc_ValueError, "Not a valid source package"); | ||
1728 | 416 | return NULL; | ||
1729 | 417 | } | ||
1730 | 418 | para = src->details; | ||
1731 | 419 | if (para) { | ||
1732 | 420 | for (i = 0; i < para->n_entries; i++) { | ||
1733 | 421 | if (strcasecmp(para->entry[i].name, field) == 0) { | ||
1734 | 422 | return Py_BuildValue("s", para->entry[i].value); | ||
1735 | 423 | } | ||
1736 | 424 | } | ||
1737 | 425 | } | ||
1738 | 426 | return Py_BuildValue(""); | ||
1739 | 427 | } | ||
1740 | 428 | |||
1741 | 429 | static PyObject *dpkgsources_ispresent(dpkgsources *self, PyObject *args) { | ||
1742 | 430 | char *srcname; | ||
1743 | 431 | if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL; | ||
1744 | 432 | if (lookup_sourcetbl(self->srcs->sources, srcname)) { | ||
1745 | 433 | return Py_BuildValue("i", 1); | ||
1746 | 434 | } else { | ||
1747 | 435 | return Py_BuildValue("i", 0); | ||
1748 | 436 | } | ||
1749 | 437 | } | ||
1750 | 438 | |||
1751 | 439 | static PyObject *dpkgsources_binaries(dpkgsources *self, PyObject *args) { | ||
1752 | 440 | char *srcname, *arch; | ||
1753 | 441 | int archnum; | ||
1754 | 442 | dpkg_source *src; | ||
1755 | 443 | PyObject *res; | ||
1756 | 444 | ownedpackagelist *p; | ||
1757 | 445 | |||
1758 | 446 | if (!PyArg_ParseTuple(args, "ss", &srcname, &arch)) return NULL; | ||
1759 | 447 | |||
1760 | 448 | for (archnum = 0; archnum < self->srcs->n_arches; archnum++) { | ||
1761 | 449 | if (strcmp(arch, self->srcs->archname[archnum]) == 0) break; | ||
1762 | 450 | } | ||
1763 | 451 | if (archnum == self->srcs->n_arches) { | ||
1764 | 452 | PyErr_SetString(PyExc_ValueError, "Not a valid architecture"); | ||
1765 | 453 | return NULL; | ||
1766 | 454 | } | ||
1767 | 455 | |||
1768 | 456 | src = lookup_sourcetbl(self->srcs->sources, srcname); | ||
1769 | 457 | if (src == NULL) { | ||
1770 | 458 | PyErr_SetString(PyExc_ValueError, "Not a valid source package"); | ||
1771 | 459 | return NULL; | ||
1772 | 460 | } | ||
1773 | 461 | |||
1774 | 462 | MAKE_PY_LIST(res, p = src->packages[archnum], p, p = p->next, | ||
1775 | 463 | ("s", p->value->package) | ||
1776 | 464 | ); | ||
1777 | 465 | return res; | ||
1778 | 466 | } | ||
1779 | 467 | |||
1780 | 468 | static PyObject *dpkgsources_getattr(dpkgsources *self, char *name) { | ||
1781 | 469 | static struct PyMethodDef dpkgsources_methods[] = { | ||
1782 | 470 | { "Packages", (binaryfunc) dpkgsources_packages, | ||
1783 | 471 | METH_VARARGS, NULL }, | ||
1784 | 472 | { "is_fake", (binaryfunc) dpkgsources_isfake, | ||
1785 | 473 | METH_VARARGS, NULL }, | ||
1786 | 474 | { "get_version", (binaryfunc) dpkgsources_getversion, | ||
1787 | 475 | METH_VARARGS, NULL }, | ||
1788 | 476 | { "get_field", (binaryfunc) dpkgsources_getfield, | ||
1789 | 477 | METH_VARARGS, NULL }, | ||
1790 | 478 | { "is_present", (binaryfunc) dpkgsources_ispresent, | ||
1791 | 479 | METH_VARARGS, NULL }, | ||
1792 | 480 | { "binaries", (binaryfunc) dpkgsources_binaries, | ||
1793 | 481 | METH_VARARGS, NULL }, | ||
1794 | 482 | { NULL, NULL, 0, NULL } | ||
1795 | 483 | }; | ||
1796 | 484 | |||
1797 | 485 | if (strcmp(name, "arches") == 0) { | ||
1798 | 486 | PyObject *arches; | ||
1799 | 487 | int i; | ||
1800 | 488 | MAKE_PY_LIST(arches, i = 0, i < self->srcs->n_arches, i++, | ||
1801 | 489 | ("s", self->srcs->archname[i]) | ||
1802 | 490 | ); | ||
1803 | 491 | return arches; | ||
1804 | 492 | } else if (strcmp(name, "sources") == 0) { | ||
1805 | 493 | PyObject *sources; | ||
1806 | 494 | sourcetbl_iter it; | ||
1807 | 495 | MAKE_PY_LIST(sources, | ||
1808 | 496 | it = first_sourcetbl(self->srcs->sources), | ||
1809 | 497 | !done_sourcetbl(it), it = next_sourcetbl(it), | ||
1810 | 498 | ("s", it.k) | ||
1811 | 499 | ); | ||
1812 | 500 | return sources; | ||
1813 | 501 | } | ||
1814 | 502 | |||
1815 | 503 | return Py_FindMethod(dpkgsources_methods, (PyObject *)self, name); | ||
1816 | 504 | } | ||
1817 | 505 | |||
1818 | 506 | static PyTypeObject Sources_Type = { | ||
1819 | 507 | PyObject_HEAD_INIT(&PyType_Type) | ||
1820 | 508 | |||
1821 | 509 | 0, /* ob_size (0) */ | ||
1822 | 510 | "Sources", /* type name */ | ||
1823 | 511 | sizeof(dpkgsources), /* basicsize */ | ||
1824 | 512 | 0, /* itemsize (0) */ | ||
1825 | 513 | |||
1826 | 514 | (destructor) dpkgsources_dealloc, | ||
1827 | 515 | (printfunc) 0, | ||
1828 | 516 | (getattrfunc) dpkgsources_getattr, | ||
1829 | 517 | (setattrfunc) 0, | ||
1830 | 518 | (cmpfunc) 0, | ||
1831 | 519 | (reprfunc) 0, | ||
1832 | 520 | |||
1833 | 521 | 0, /* number methods */ | ||
1834 | 522 | 0, /* sequence methods */ | ||
1835 | 523 | 0, /* mapping methods */ | ||
1836 | 524 | |||
1837 | 525 | (hashfunc) 0, /* dict[x] ?? */ | ||
1838 | 526 | (ternaryfunc) 0, /* x() */ | ||
1839 | 527 | (reprfunc) 0 /* str(x) */ | ||
1840 | 528 | }; | ||
1841 | 529 | |||
1842 | 530 | /************************************************************************** | ||
1843 | 531 | * britney.SourcesNote -- dpkg_sourcesnote wrapper | ||
1844 | 532 | *************************************************/ | ||
1845 | 533 | |||
1846 | 534 | typedef struct { | ||
1847 | 535 | PyObject_HEAD | ||
1848 | 536 | dpkg_sources_note *srcsn; | ||
1849 | 537 | PyObject *refs; /* list of referenced dpkgsources */ | ||
1850 | 538 | } dpkgsrcsn; | ||
1851 | 539 | |||
1852 | 540 | staticforward PyTypeObject SourcesNote_Type; | ||
1853 | 541 | |||
1854 | 542 | static PyObject *dpkgsrcsn_new(PyObject *self, PyObject *args) { | ||
1855 | 543 | dpkgsrcsn *res = NULL; | ||
1856 | 544 | PyObject *arches; | ||
1857 | 545 | char **archesStr = NULL; | ||
1858 | 546 | int i, count; | ||
1859 | 547 | |||
1860 | 548 | (void)self; /* unused */ | ||
1861 | 549 | |||
1862 | 550 | if (!PyArg_ParseTuple(args, "O!", &PyList_Type, &arches)) { | ||
1863 | 551 | goto end; | ||
1864 | 552 | } | ||
1865 | 553 | |||
1866 | 554 | count = PyList_Size(arches); | ||
1867 | 555 | if (count <= 0) { | ||
1868 | 556 | PyErr_SetString(PyExc_TypeError, "No architectures specified"); | ||
1869 | 557 | goto end; | ||
1870 | 558 | } | ||
1871 | 559 | |||
1872 | 560 | archesStr = malloc(sizeof(char *) * count); | ||
1873 | 561 | if (!archesStr) { | ||
1874 | 562 | PyErr_SetFromErrno(PyExc_MemoryError); | ||
1875 | 563 | goto end; | ||
1876 | 564 | } | ||
1877 | 565 | |||
1878 | 566 | for (i = 0; i < count; i++) { | ||
1879 | 567 | PyObject *arch = PyList_GetItem(arches, i); | ||
1880 | 568 | if (!PyString_Check(arch)) { | ||
1881 | 569 | goto end; | ||
1882 | 570 | } | ||
1883 | 571 | archesStr[i] = PyString_AsString(arch); | ||
1884 | 572 | } | ||
1885 | 573 | |||
1886 | 574 | res = PyObject_NEW(dpkgsrcsn, &SourcesNote_Type); | ||
1887 | 575 | if (res == NULL) goto end; | ||
1888 | 576 | |||
1889 | 577 | res->refs = PyList_New(0); | ||
1890 | 578 | res->srcsn = new_sources_note(count, archesStr); | ||
1891 | 579 | if (!res->refs || !res->srcsn) { | ||
1892 | 580 | Py_DECREF(res); | ||
1893 | 581 | res = NULL; | ||
1894 | 582 | goto end; | ||
1895 | 583 | } | ||
1896 | 584 | |||
1897 | 585 | end: | ||
1898 | 586 | if (archesStr) free(archesStr); | ||
1899 | 587 | return (PyObject *) res; | ||
1900 | 588 | } | ||
1901 | 589 | |||
1902 | 590 | static void dpkgsrcsn_dealloc(dpkgsrcsn *self) { | ||
1903 | 591 | if (self->srcsn) free_sources_note(self->srcsn); | ||
1904 | 592 | self->srcsn = NULL; | ||
1905 | 593 | Py_XDECREF(self->refs); | ||
1906 | 594 | self->refs = NULL; | ||
1907 | 595 | |||
1908 | 596 | PyObject_DEL(self); | ||
1909 | 597 | } | ||
1910 | 598 | |||
1911 | 599 | static PyObject *dpkgsrcsn_removesource(dpkgsrcsn *self, PyObject *args) { | ||
1912 | 600 | char *name; | ||
1913 | 601 | if (!PyArg_ParseTuple(args, "s", &name)) return NULL; | ||
1914 | 602 | remove_source(self->srcsn, name); | ||
1915 | 603 | return Py_BuildValue(""); | ||
1916 | 604 | } | ||
1917 | 605 | static PyObject *dpkgsrcsn_upgradesource(dpkgsrcsn *self, PyObject *args) { | ||
1918 | 606 | char *name; | ||
1919 | 607 | dpkgsources *srcs; | ||
1920 | 608 | dpkg_source *src; | ||
1921 | 609 | if (!PyArg_ParseTuple(args, "O!s", &Sources_Type, &srcs, &name)) | ||
1922 | 610 | return NULL; | ||
1923 | 611 | src = lookup_sourcetbl(srcs->srcs->sources, name); | ||
1924 | 612 | if (!src) { | ||
1925 | 613 | PyErr_SetString(PyExc_ValueError, "Source does not exist"); | ||
1926 | 614 | return NULL; | ||
1927 | 615 | } | ||
1928 | 616 | if (!PySequence_In(self->refs, (PyObject *)srcs)) | ||
1929 | 617 | PyList_Append(self->refs, (PyObject *)srcs); | ||
1930 | 618 | upgrade_source(self->srcsn, src); | ||
1931 | 619 | return Py_BuildValue(""); | ||
1932 | 620 | } | ||
1933 | 621 | static PyObject *dpkgsrcsn_upgradearch(dpkgsrcsn *self, PyObject *args) { | ||
1934 | 622 | char *name, *arch; | ||
1935 | 623 | dpkgsources *srcs; | ||
1936 | 624 | dpkg_source *src; | ||
1937 | 625 | if (!PyArg_ParseTuple(args, "O!ss", &Sources_Type, &srcs, &name, &arch)) | ||
1938 | 626 | return NULL; | ||
1939 | 627 | src = lookup_sourcetbl(srcs->srcs->sources, name); | ||
1940 | 628 | if (!src) { | ||
1941 | 629 | PyErr_SetString(PyExc_ValueError, "Source does not exist"); | ||
1942 | 630 | return NULL; | ||
1943 | 631 | } | ||
1944 | 632 | if (!PySequence_In(self->refs, (PyObject *)srcs)) | ||
1945 | 633 | PyList_Append(self->refs, (PyObject *)srcs); | ||
1946 | 634 | upgrade_arch(self->srcsn, src, arch); | ||
1947 | 635 | return Py_BuildValue(""); | ||
1948 | 636 | } | ||
1949 | 637 | |||
1950 | 638 | static PyObject *dpkgsrcsn_undochange(dpkgsrcsn *self, PyObject *args) { | ||
1951 | 639 | if (!PyArg_ParseTuple(args, "")) return NULL; | ||
1952 | 640 | undo_change(self->srcsn); | ||
1953 | 641 | return Py_BuildValue(""); | ||
1954 | 642 | } | ||
1955 | 643 | |||
1956 | 644 | static PyObject *dpkgsrcsn_commitchanges(dpkgsrcsn *self, PyObject *args) { | ||
1957 | 645 | if (!PyArg_ParseTuple(args, "")) return NULL; | ||
1958 | 646 | commit_changes(self->srcsn); | ||
1959 | 647 | return Py_BuildValue(""); | ||
1960 | 648 | } | ||
1961 | 649 | |||
1962 | 650 | static PyObject *dpkgsrcsn_writenotes(dpkgsrcsn *self, PyObject *args) { | ||
1963 | 651 | char *dir; | ||
1964 | 652 | if (!PyArg_ParseTuple(args, "s", &dir)) return NULL; | ||
1965 | 653 | write_notes(dir, self->srcsn); | ||
1966 | 654 | return Py_BuildValue(""); | ||
1967 | 655 | } | ||
1968 | 656 | |||
1969 | 657 | static PyObject *dpkgsrcsn_packages(dpkgsrcsn *self, PyObject *args) { | ||
1970 | 658 | char *arch; | ||
1971 | 659 | int archnum; | ||
1972 | 660 | if (!PyArg_ParseTuple(args, "s", &arch)) return NULL; | ||
1973 | 661 | for (archnum = 0; archnum < self->srcsn->n_arches; archnum++) { | ||
1974 | 662 | if (strcmp(arch, self->srcsn->archname[archnum]) == 0) break; | ||
1975 | 663 | } | ||
1976 | 664 | if (archnum == self->srcsn->n_arches) { | ||
1977 | 665 | PyErr_SetString(PyExc_ValueError, "Not a valid architecture"); | ||
1978 | 666 | return NULL; | ||
1979 | 667 | } | ||
1980 | 668 | return dpkgpackages_new(self->srcsn->pkgs[archnum], DONTFREE, | ||
1981 | 669 | (PyObject *) self); | ||
1982 | 670 | } | ||
1983 | 671 | |||
1984 | 672 | static PyObject *dpkgsrcsn_getversion(dpkgsrcsn *self, PyObject *args) { | ||
1985 | 673 | char *srcname; | ||
1986 | 674 | dpkg_source_note *srcn; | ||
1987 | 675 | |||
1988 | 676 | if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL; | ||
1989 | 677 | srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname); | ||
1990 | 678 | if (srcn) return Py_BuildValue("s", srcn->source->version); | ||
1991 | 679 | else return Py_BuildValue(""); | ||
1992 | 680 | } | ||
1993 | 681 | static PyObject *dpkgsrcsn_getfield(dpkgsrcsn *self, PyObject *args) { | ||
1994 | 682 | char *srcname, *field; | ||
1995 | 683 | dpkg_source_note *srcn; | ||
1996 | 684 | int i; | ||
1997 | 685 | dpkg_paragraph *para; | ||
1998 | 686 | |||
1999 | 687 | if (!PyArg_ParseTuple(args, "ss", &srcname, &field)) return NULL; | ||
2000 | 688 | srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname); | ||
2001 | 689 | if (!srcn) { | ||
2002 | 690 | PyErr_SetString(PyExc_ValueError, "Not a valid source package"); | ||
2003 | 691 | return NULL; | ||
2004 | 692 | } | ||
2005 | 693 | para = srcn->source->details; | ||
2006 | 694 | if (para) { | ||
2007 | 695 | for (i = 0; i < para->n_entries; i++) { | ||
2008 | 696 | if (strcasecmp(para->entry[i].name, field) == 0) { | ||
2009 | 697 | return Py_BuildValue("s", para->entry[i].value); | ||
2010 | 698 | } | ||
2011 | 699 | } | ||
2012 | 700 | } | ||
2013 | 701 | return Py_BuildValue(""); | ||
2014 | 702 | } | ||
2015 | 703 | static PyObject *dpkgsrcsn_ispresent(dpkgsrcsn *self, PyObject *args) { | ||
2016 | 704 | char *srcname; | ||
2017 | 705 | if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL; | ||
2018 | 706 | if (lookup_sourcenotetbl(self->srcsn->sources, srcname)) { | ||
2019 | 707 | return Py_BuildValue("i", 1); | ||
2020 | 708 | } else { | ||
2021 | 709 | return Py_BuildValue("i", 0); | ||
2022 | 710 | } | ||
2023 | 711 | } | ||
2024 | 712 | |||
2025 | 713 | static PyObject *dpkgsrcsn_isfake(dpkgsrcsn *self, PyObject *args) { | ||
2026 | 714 | char *srcname; | ||
2027 | 715 | dpkg_source_note *srcn; | ||
2028 | 716 | |||
2029 | 717 | if (!PyArg_ParseTuple(args, "s", &srcname)) return NULL; | ||
2030 | 718 | srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname); | ||
2031 | 719 | if (srcn) return Py_BuildValue("i", srcn->source->fake); | ||
2032 | 720 | else return Py_BuildValue(""); | ||
2033 | 721 | } | ||
2034 | 722 | |||
2035 | 723 | static PyObject *dpkgsrcsn_binaries(dpkgsrcsn *self, PyObject *args) { | ||
2036 | 724 | char *srcname, *arch; | ||
2037 | 725 | int archnum; | ||
2038 | 726 | dpkg_source_note *srcn; | ||
2039 | 727 | PyObject *res; | ||
2040 | 728 | packagelist *p; | ||
2041 | 729 | |||
2042 | 730 | if (!PyArg_ParseTuple(args, "ss", &srcname, &arch)) return NULL; | ||
2043 | 731 | |||
2044 | 732 | for (archnum = 0; archnum < self->srcsn->n_arches; archnum++) { | ||
2045 | 733 | if (strcmp(arch, self->srcsn->archname[archnum]) == 0) break; | ||
2046 | 734 | } | ||
2047 | 735 | if (archnum == self->srcsn->n_arches) { | ||
2048 | 736 | PyErr_SetString(PyExc_ValueError, "Not a valid architecture"); | ||
2049 | 737 | return NULL; | ||
2050 | 738 | } | ||
2051 | 739 | |||
2052 | 740 | srcn = lookup_sourcenotetbl(self->srcsn->sources, srcname); | ||
2053 | 741 | if (srcn == NULL) { | ||
2054 | 742 | PyErr_SetString(PyExc_ValueError, "Not a valid source package"); | ||
2055 | 743 | return NULL; | ||
2056 | 744 | } | ||
2057 | 745 | |||
2058 | 746 | MAKE_PY_LIST(res, p = srcn->binaries[archnum], p, p = p->next, | ||
2059 | 747 | ("s", p->value->package) | ||
2060 | 748 | ); | ||
2061 | 749 | return res; | ||
2062 | 750 | } | ||
2063 | 751 | |||
2064 | 752 | static PyObject *dpkgsrcsn_getattr(dpkgsrcsn *self, char *name) { | ||
2065 | 753 | static struct PyMethodDef dpkgsrcsn_methods[] = { | ||
2066 | 754 | { "remove_source", (binaryfunc) dpkgsrcsn_removesource, | ||
2067 | 755 | METH_VARARGS, NULL }, | ||
2068 | 756 | { "upgrade_source", (binaryfunc) dpkgsrcsn_upgradesource, | ||
2069 | 757 | METH_VARARGS, NULL }, | ||
2070 | 758 | { "upgrade_arch", (binaryfunc) dpkgsrcsn_upgradearch, | ||
2071 | 759 | METH_VARARGS, NULL }, | ||
2072 | 760 | |||
2073 | 761 | { "undo_change", (binaryfunc) dpkgsrcsn_undochange, | ||
2074 | 762 | METH_VARARGS, NULL }, | ||
2075 | 763 | { "commit_changes", (binaryfunc) dpkgsrcsn_commitchanges, | ||
2076 | 764 | METH_VARARGS, NULL }, | ||
2077 | 765 | |||
2078 | 766 | { "write_notes", (binaryfunc) dpkgsrcsn_writenotes, | ||
2079 | 767 | METH_VARARGS, NULL }, | ||
2080 | 768 | |||
2081 | 769 | { "Packages", (binaryfunc) dpkgsrcsn_packages, | ||
2082 | 770 | METH_VARARGS, NULL }, | ||
2083 | 771 | |||
2084 | 772 | { "get_version", (binaryfunc) dpkgsrcsn_getversion, | ||
2085 | 773 | METH_VARARGS, NULL }, | ||
2086 | 774 | { "get_field", (binaryfunc) dpkgsrcsn_getfield, | ||
2087 | 775 | METH_VARARGS, NULL }, | ||
2088 | 776 | { "is_present", (binaryfunc) dpkgsrcsn_ispresent, | ||
2089 | 777 | METH_VARARGS, NULL }, | ||
2090 | 778 | { "is_fake", (binaryfunc) dpkgsrcsn_isfake, | ||
2091 | 779 | METH_VARARGS, NULL }, | ||
2092 | 780 | { "binaries", (binaryfunc) dpkgsrcsn_binaries, | ||
2093 | 781 | METH_VARARGS, NULL }, | ||
2094 | 782 | { NULL, NULL, 0, NULL } | ||
2095 | 783 | }; | ||
2096 | 784 | |||
2097 | 785 | if (strcmp(name, "arches") == 0) { | ||
2098 | 786 | PyObject *arches; | ||
2099 | 787 | int i; | ||
2100 | 788 | MAKE_PY_LIST(arches, i = 0, i < self->srcsn->n_arches, i++, | ||
2101 | 789 | ("s", self->srcsn->archname[i]) | ||
2102 | 790 | ); | ||
2103 | 791 | return arches; | ||
2104 | 792 | } else if (strcmp(name, "sources") == 0) { | ||
2105 | 793 | PyObject *sources; | ||
2106 | 794 | sourcenotetbl_iter it; | ||
2107 | 795 | MAKE_PY_LIST(sources, | ||
2108 | 796 | it = first_sourcenotetbl(self->srcsn->sources), | ||
2109 | 797 | !done_sourcenotetbl(it), | ||
2110 | 798 | it = next_sourcenotetbl(it), | ||
2111 | 799 | ("s", it.k) | ||
2112 | 800 | ); | ||
2113 | 801 | return sources; | ||
2114 | 802 | } else if (strcmp(name, "can_undo") == 0) { | ||
2115 | 803 | if (can_undo(self->srcsn)) { | ||
2116 | 804 | return Py_BuildValue("i", 1); | ||
2117 | 805 | } else { | ||
2118 | 806 | return Py_BuildValue(""); | ||
2119 | 807 | } | ||
2120 | 808 | } | ||
2121 | 809 | |||
2122 | 810 | return Py_FindMethod(dpkgsrcsn_methods, (PyObject *)self, name); | ||
2123 | 811 | } | ||
2124 | 812 | |||
2125 | 813 | static PyTypeObject SourcesNote_Type = { | ||
2126 | 814 | PyObject_HEAD_INIT(&PyType_Type) | ||
2127 | 815 | |||
2128 | 816 | 0, /* ob_size (0) */ | ||
2129 | 817 | "SourcesNote", /* type name */ | ||
2130 | 818 | sizeof(dpkgsrcsn), /* basicsize */ | ||
2131 | 819 | 0, /* itemsize (0) */ | ||
2132 | 820 | |||
2133 | 821 | (destructor) dpkgsrcsn_dealloc, | ||
2134 | 822 | (printfunc) 0, | ||
2135 | 823 | (getattrfunc) dpkgsrcsn_getattr, | ||
2136 | 824 | (setattrfunc) 0, | ||
2137 | 825 | (cmpfunc) 0, | ||
2138 | 826 | (reprfunc) 0, | ||
2139 | 827 | |||
2140 | 828 | 0, /* number methods */ | ||
2141 | 829 | 0, /* sequence methods */ | ||
2142 | 830 | 0, /* mapping methods */ | ||
2143 | 831 | |||
2144 | 832 | (hashfunc) 0, /* dict[x] ?? */ | ||
2145 | 833 | (ternaryfunc) 0, /* x() */ | ||
2146 | 834 | (reprfunc) 0 /* str(x) */ | ||
2147 | 835 | }; | ||
2148 | 836 | |||
2149 | 837 | /************************************************************************** | ||
2150 | 838 | * britney.versioncmp() -- apt version compare function | ||
2151 | 839 | ******************************************************/ | ||
2152 | 840 | |||
2153 | 841 | static PyObject *apt_versioncmp(PyObject *self, PyObject *args) { | ||
2154 | 842 | char *l, *r; | ||
2155 | 843 | int res; | ||
2156 | 844 | |||
2157 | 845 | (void)self; /* unused */ | ||
2158 | 846 | |||
2159 | 847 | if (!PyArg_ParseTuple(args, "ss", &l, &r)) { | ||
2160 | 848 | return NULL; | ||
2161 | 849 | } | ||
2162 | 850 | |||
2163 | 851 | res = versioncmp(l,r); | ||
2164 | 852 | return Py_BuildValue("i", res); | ||
2165 | 853 | } | ||
2166 | 854 | |||
2167 | 855 | /************************************************************************** | ||
2168 | 856 | * module initialisation | ||
2169 | 857 | ***********************/ | ||
2170 | 858 | |||
2171 | 859 | static PyMethodDef britneymethods[] = { | ||
2172 | 860 | { "Sources", dpkgsources_new, METH_VARARGS, NULL }, | ||
2173 | 861 | { "SourcesNote", dpkgsrcsn_new, METH_VARARGS, NULL }, | ||
2174 | 862 | |||
2175 | 863 | { "versioncmp", apt_versioncmp, METH_VARARGS, NULL }, | ||
2176 | 864 | |||
2177 | 865 | { NULL, NULL, 0, NULL } | ||
2178 | 866 | }; | ||
2179 | 867 | |||
2180 | 868 | void initbritney(void) { | ||
2181 | 869 | Py_InitModule("britney", britneymethods); | ||
2182 | 870 | } | ||
2183 | 871 | |||
2184 | 0 | 872 | ||
2185 | === added file 'update_out/checklib.c' | |||
2186 | --- update_out/checklib.c 1970-01-01 00:00:00 +0000 | |||
2187 | +++ update_out/checklib.c 2015-06-09 16:34:27 +0000 | |||
2188 | @@ -0,0 +1,185 @@ | |||
2189 | 1 | #include <stdlib.h> | ||
2190 | 2 | #include <unistd.h> | ||
2191 | 3 | |||
2192 | 4 | #include <assert.h> | ||
2193 | 5 | |||
2194 | 6 | #include "dpkg.h" | ||
2195 | 7 | |||
2196 | 8 | #if 0 | ||
2197 | 9 | static void checknewsrc(sourcetbl *srcstbl, dpkg_source *cur, void *data) { | ||
2198 | 10 | dpkg_sources *oldsrc = data; | ||
2199 | 11 | dpkg_source *old; | ||
2200 | 12 | old = lookup_sourcetbl(oldsrc->sources, cur->package); | ||
2201 | 13 | if (old == NULL) { | ||
2202 | 14 | printf("New: %s (%s)\n", cur->package, cur->version ); | ||
2203 | 15 | } else if (strcmp(old->version, cur->version) != 0) { | ||
2204 | 16 | printf("Updated: %s (%s, was %s)\n", | ||
2205 | 17 | cur->package, cur->version, old->version ); | ||
2206 | 18 | } else { | ||
2207 | 19 | dpkg_source *src2; | ||
2208 | 20 | src2 = remove_sourcetbl(srcstbl, cur->package); | ||
2209 | 21 | assert(cur == src2); | ||
2210 | 22 | free_source(cur); | ||
2211 | 23 | } | ||
2212 | 24 | } | ||
2213 | 25 | |||
2214 | 26 | static void checkoldsrc(sourcetbl *oldsrctbl, dpkg_source *old, void *data) { | ||
2215 | 27 | dpkg_sources *src = data; | ||
2216 | 28 | dpkg_source *cur; | ||
2217 | 29 | (void)oldsrctbl; | ||
2218 | 30 | cur = lookup_sourcetbl(src->sources, old->package); | ||
2219 | 31 | if (cur == NULL) { | ||
2220 | 32 | printf("Removed: %s (was %s)\n", old->package, old->version ); | ||
2221 | 33 | } | ||
2222 | 34 | } | ||
2223 | 35 | |||
2224 | 36 | static void checkuptodate(sourcetbl *srctbl, dpkg_source *src, void *data) { | ||
2225 | 37 | int i; | ||
2226 | 38 | int remove; | ||
2227 | 39 | ownedpackagelist **p; | ||
2228 | 40 | dpkg_sources *srcs = data; | ||
2229 | 41 | |||
2230 | 42 | (void)srctbl; | ||
2231 | 43 | |||
2232 | 44 | remove = 0; | ||
2233 | 45 | for (i = 0; i < srcs->n_arches; i++) { | ||
2234 | 46 | p = &src->packages[i]; | ||
2235 | 47 | while(*p != NULL) { | ||
2236 | 48 | if (strcmp((*p)->value->source_ver, src->version) != 0) { | ||
2237 | 49 | if (cmpversions((*p)->value->source_ver, GT, src->version)) { | ||
2238 | 50 | printf("ALERT: old source: "); | ||
2239 | 51 | } else { | ||
2240 | 52 | printf("WARN: out of date: "); | ||
2241 | 53 | } | ||
2242 | 54 | printf("%s %s: %s binary: %s %s from %s\n", | ||
2243 | 55 | src->package, src->version, srcs->archname[i], | ||
2244 | 56 | (*p)->value->package, (*p)->value->version, | ||
2245 | 57 | (*p)->value->source_ver); | ||
2246 | 58 | delete_ownedpackagelist(p); | ||
2247 | 59 | } else { | ||
2248 | 60 | p = &(*p)->next; | ||
2249 | 61 | } | ||
2250 | 62 | } | ||
2251 | 63 | if (src->packages[i] == NULL) { | ||
2252 | 64 | printf("%s missing uptodate binaries for %s\n", | ||
2253 | 65 | src->package, srcs->archname[i]); | ||
2254 | 66 | remove = 1; | ||
2255 | 67 | } | ||
2256 | 68 | } | ||
2257 | 69 | if (remove) { | ||
2258 | 70 | dpkg_source *src2; | ||
2259 | 71 | src2 = remove_sourcetbl(srcs->sources, src->package); | ||
2260 | 72 | assert(src == src2); | ||
2261 | 73 | free_source(src); | ||
2262 | 74 | } | ||
2263 | 75 | } | ||
2264 | 76 | #endif | ||
2265 | 77 | |||
2266 | 78 | static void upgrade(sourcetbl *srctbl, dpkg_source *src, void *data) { | ||
2267 | 79 | static int i = 0; | ||
2268 | 80 | dpkg_sources_note *srcsn = data; | ||
2269 | 81 | (void)srctbl; | ||
2270 | 82 | i++; i %= 1000; | ||
2271 | 83 | if (can_undo(srcsn)) { | ||
2272 | 84 | if (i % 29 == 1 || i % 31 == 1 || i % 7 == 5) | ||
2273 | 85 | undo_change(srcsn); | ||
2274 | 86 | if (i % 33 == 0) commit_changes(srcsn); | ||
2275 | 87 | } | ||
2276 | 88 | upgrade_source(data, src); | ||
2277 | 89 | } | ||
2278 | 90 | |||
2279 | 91 | static void checkpkgs(packagetbl *pkgtbl, dpkg_collected_package *cpkg, | ||
2280 | 92 | void *data) | ||
2281 | 93 | { | ||
2282 | 94 | dpkg_packages *pkgs = data; | ||
2283 | 95 | assert(pkgs->packages == pkgtbl); | ||
2284 | 96 | printf("Trying %s (%s, %s)\n", cpkg->pkg->package, cpkg->pkg->version, pkgs->arch); | ||
2285 | 97 | if (!checkinstallable2(pkgs, cpkg->pkg->package)) { | ||
2286 | 98 | printf("Package: %s (%s, %s) is uninstallable\n", | ||
2287 | 99 | cpkg->pkg->package, cpkg->pkg->version, pkgs->arch); | ||
2288 | 100 | } | ||
2289 | 101 | } | ||
2290 | 102 | |||
2291 | 103 | void print_memblock_summary(void); | ||
2292 | 104 | |||
2293 | 105 | int main(int argc, char **argv) { | ||
2294 | 106 | dpkg_sources *src = NULL, *oldsrc = NULL; | ||
2295 | 107 | dpkg_sources_note *srcsn; | ||
2296 | 108 | dpkg_source *srcpkg; | ||
2297 | 109 | dpkg_packages *pkgs[10]; | ||
2298 | 110 | int n_pkgs; | ||
2299 | 111 | int i,j; | ||
2300 | 112 | int reps; | ||
2301 | 113 | |||
2302 | 114 | if (argc < 3) { | ||
2303 | 115 | printf("Usage: %s <reps> <arch>...\n", argv[0]); | ||
2304 | 116 | exit(EXIT_FAILURE); | ||
2305 | 117 | } | ||
2306 | 118 | |||
2307 | 119 | reps = atoi(argv[1]); | ||
2308 | 120 | if (reps < 1) { | ||
2309 | 121 | printf("reps must be >= 1\n"); | ||
2310 | 122 | exit(EXIT_FAILURE); | ||
2311 | 123 | } | ||
2312 | 124 | |||
2313 | 125 | src = read_directory("cur", argc - 2, argv + 2); | ||
2314 | 126 | oldsrc = read_directory("old", argc - 2, argv + 2); | ||
2315 | 127 | srcsn = new_sources_note(argc - 2, argv + 2); | ||
2316 | 128 | |||
2317 | 129 | printf("FINISHED LOADING\n"); fflush(stdout); /* sleep(5); */ | ||
2318 | 130 | |||
2319 | 131 | #if 0 | ||
2320 | 132 | iterate_sourcetbl(oldsrc->sources, checkoldsrc, src); | ||
2321 | 133 | |||
2322 | 134 | printf("FIRST\n"); | ||
2323 | 135 | iterate_sourcetbl(src->sources, checkuptodate, src); | ||
2324 | 136 | printf("SECOND\n"); | ||
2325 | 137 | iterate_sourcetbl(src->sources, checkuptodate, src); | ||
2326 | 138 | printf("END\n"); | ||
2327 | 139 | |||
2328 | 140 | iterate_sourcetbl(src->sources, checknewsrc, oldsrc); | ||
2329 | 141 | #endif | ||
2330 | 142 | |||
2331 | 143 | n_pkgs = 0; | ||
2332 | 144 | for (i = argc - 1; i > 1; i--) { | ||
2333 | 145 | pkgs[n_pkgs++] = get_architecture(oldsrc, argv[i]); | ||
2334 | 146 | } | ||
2335 | 147 | for (j = 0; j < reps; j++) { | ||
2336 | 148 | printf("Round %d/%d starting...\n", j + 1, reps); | ||
2337 | 149 | for (i = 0; i < n_pkgs; i++) { | ||
2338 | 150 | iterate_packagetbl(pkgs[i]->packages, checkpkgs, pkgs[i]); | ||
2339 | 151 | } | ||
2340 | 152 | printf("Round %d ended.\n", j+1); | ||
2341 | 153 | } | ||
2342 | 154 | iterate_sourcetbl(src->sources, upgrade, srcsn); | ||
2343 | 155 | iterate_sourcetbl(oldsrc->sources, upgrade, srcsn); | ||
2344 | 156 | |||
2345 | 157 | for (i = 0; i < n_pkgs; i++) { | ||
2346 | 158 | free_packages(pkgs[i]); | ||
2347 | 159 | } | ||
2348 | 160 | |||
2349 | 161 | srcpkg = lookup_sourcetbl(oldsrc->sources, "omirr"); | ||
2350 | 162 | if (srcpkg != NULL) { | ||
2351 | 163 | printf("Adding old\n"); | ||
2352 | 164 | upgrade_source(srcsn, srcpkg); | ||
2353 | 165 | } | ||
2354 | 166 | srcpkg = lookup_sourcetbl(src->sources, "omirr"); | ||
2355 | 167 | if (srcpkg != NULL) { | ||
2356 | 168 | printf("Adding cur\n"); | ||
2357 | 169 | upgrade_source(srcsn, srcpkg); | ||
2358 | 170 | } | ||
2359 | 171 | |||
2360 | 172 | printf("FINISHED PROCESSING\n"); fflush(stdout); /* sleep(5); */ | ||
2361 | 173 | |||
2362 | 174 | write_directory("out", oldsrc); | ||
2363 | 175 | |||
2364 | 176 | printf("FINISHED WRITING\n"); fflush(stdout); /* sleep(5); */ | ||
2365 | 177 | |||
2366 | 178 | free_sources_note(srcsn); | ||
2367 | 179 | free_sources(src); | ||
2368 | 180 | free_sources(oldsrc); | ||
2369 | 181 | |||
2370 | 182 | DEBUG_ONLY( print_memblock_summary(); ) | ||
2371 | 183 | |||
2372 | 184 | return 0; | ||
2373 | 185 | } | ||
2374 | 0 | 186 | ||
2375 | === added file 'update_out/dpkg-lib.cpp' | |||
2376 | --- update_out/dpkg-lib.cpp 1970-01-01 00:00:00 +0000 | |||
2377 | +++ update_out/dpkg-lib.cpp 2015-06-09 16:34:27 +0000 | |||
2378 | @@ -0,0 +1,34 @@ | |||
2379 | 1 | |||
2380 | 2 | #include <apt-pkg/debversion.h> | ||
2381 | 3 | |||
2382 | 4 | extern "C" { | ||
2383 | 5 | |||
2384 | 6 | #include "dpkg.h" | ||
2385 | 7 | |||
2386 | 8 | int versioncmp(char *left, char *right) { | ||
2387 | 9 | return debVS.CmpVersion(left, right); | ||
2388 | 10 | } | ||
2389 | 11 | |||
2390 | 12 | int cmpversions(char *left, int op, char *right) { | ||
2391 | 13 | int i = debVS.CmpVersion(left, right); | ||
2392 | 14 | |||
2393 | 15 | switch(op) { | ||
2394 | 16 | case dr_LT: return i < 0; | ||
2395 | 17 | case dr_LTEQ: return i <= 0; | ||
2396 | 18 | case dr_EQ: return i == 0; | ||
2397 | 19 | case dr_GTEQ: return i >= 0; | ||
2398 | 20 | case dr_GT: return i > 0; | ||
2399 | 21 | } | ||
2400 | 22 | return 0; | ||
2401 | 23 | } | ||
2402 | 24 | |||
2403 | 25 | } | ||
2404 | 26 | |||
2405 | 27 | #ifdef TESTBIN | ||
2406 | 28 | int main(int argc, char **argv) { | ||
2407 | 29 | if (argc != 3) { printf("Usage: %s <ver> <ver>\n", argv[0]); exit(1); } | ||
2408 | 30 | |||
2409 | 31 | printf("%d\n", versioncmp(argv[1], argv[2])); | ||
2410 | 32 | return 0; | ||
2411 | 33 | } | ||
2412 | 34 | #endif | ||
2413 | 0 | 35 | ||
2414 | === added file 'update_out/dpkg.c' | |||
2415 | --- update_out/dpkg.c 1970-01-01 00:00:00 +0000 | |||
2416 | +++ update_out/dpkg.c 2015-06-09 16:34:27 +0000 | |||
2417 | @@ -0,0 +1,2013 @@ | |||
2418 | 1 | #include <stdio.h> | ||
2419 | 2 | #include <stdlib.h> | ||
2420 | 3 | #include <string.h> | ||
2421 | 4 | #include <ctype.h> | ||
2422 | 5 | #include <errno.h> | ||
2423 | 6 | |||
2424 | 7 | #include "dpkg.h" | ||
2425 | 8 | #include "memory.h" | ||
2426 | 9 | |||
2427 | 10 | |||
2428 | 11 | // enlarge this is britney has issues to parse packages | ||
2429 | 12 | #define SIZEOFHASHMAP 16 | ||
2430 | 13 | |||
2431 | 14 | #define insert_packagenamelist(x,y) insert_l_packagenamelist(x,y,__LINE__) | ||
2432 | 15 | |||
2433 | 16 | static void free_dependency(dependency *dep); | ||
2434 | 17 | static void free_package(dpkg_package *pkg); | ||
2435 | 18 | static void free_collected_package(dpkg_collected_package *pkg); | ||
2436 | 19 | static dpkg_paragraph *read_paragraph( FILE *f ); | ||
2437 | 20 | static dpkg_package *read_package( FILE *f ); | ||
2438 | 21 | static collpackagelist **get_matching_low(collpackagelist **addto, | ||
2439 | 22 | dpkg_packages *pkgs, dependency *dep, int line); | ||
2440 | 23 | static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line); | ||
2441 | 24 | static deplist *read_dep_and(char *buf); | ||
2442 | 25 | static deplistlist *read_dep_andor(char *buf); | ||
2443 | 26 | static ownedpackagenamelist *read_packagenames(char *buf); | ||
2444 | 27 | static dpkg_sources *read_sources_file(char *filename, int n_arches); | ||
2445 | 28 | static dpkg_source *new_source(dpkg_sources *owner); | ||
2446 | 29 | static dpkg_source *read_source(FILE *f, dpkg_sources *owner); | ||
2447 | 30 | static deplist *read_deplist(char **buf, char sep, char end); | ||
2448 | 31 | static dependency *read_dependency(char **buf, char *end); | ||
2449 | 32 | static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package, | ||
2450 | 33 | char *version, dpkg_collected_package *cpkg); | ||
2451 | 34 | static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname, | ||
2452 | 35 | dpkg_collected_package *cpkg); | ||
2453 | 36 | static char *read_packagename(char **buf, char *end); | ||
2454 | 37 | static char *read_until_char(char **buf, char *end); | ||
2455 | 38 | static void add_package(dpkg_packages *pkgs, dpkg_package *pkg); | ||
2456 | 39 | static void remove_package(dpkg_packages *pkgs, dpkg_collected_package *pkg); | ||
2457 | 40 | static dpkg_source_note *copy_source_note(dpkg_source_note *srcn); | ||
2458 | 41 | |||
2459 | 42 | #if 0 | ||
2460 | 43 | static inline void *bm(size_t s, int n) { void *res = block_malloc(s); fprintf(stderr, "ALLOCED: %d %p %lu\n", n, res, s); return res; } | ||
2461 | 44 | static inline void bf(void *p, size_t s, int n) { block_free(p,s); fprintf(stderr, "FREED: %d %p %lu\n", n, p, s); } | ||
2462 | 45 | |||
2463 | 46 | #define block_malloc(s) bm(s,__LINE__) | ||
2464 | 47 | #define block_free(p,s) bf(p,s,__LINE__) | ||
2465 | 48 | #endif | ||
2466 | 49 | |||
2467 | 50 | #define block_malloc(s) block_malloc2(s, __LINE__) | ||
2468 | 51 | |||
2469 | 52 | static char *priorities[] = { | ||
2470 | 53 | "required", | ||
2471 | 54 | "important", | ||
2472 | 55 | "standard", | ||
2473 | 56 | "optional", | ||
2474 | 57 | "extra", | ||
2475 | 58 | NULL | ||
2476 | 59 | }; | ||
2477 | 60 | |||
2478 | 61 | static char *dependency_title[] = { | ||
2479 | 62 | "Pre-Depends", "Depends", "Recommends", "Suggests", NULL | ||
2480 | 63 | }; | ||
2481 | 64 | |||
2482 | 65 | static int dependency_counts[] = { 1, 1, 0, 0 }; | ||
2483 | 66 | |||
2484 | 67 | char *dependency_relation_sym[] = {"*", "<<", "<=", "=", ">=", ">>"}; | ||
2485 | 68 | |||
2486 | 69 | #define SMB_SIZE (1<<22) | ||
2487 | 70 | struct stringmemblock { | ||
2488 | 71 | struct stringmemblock *next; | ||
2489 | 72 | size_t last; | ||
2490 | 73 | char mem[SMB_SIZE]; | ||
2491 | 74 | }; | ||
2492 | 75 | static struct stringmemblock *stringmemory = NULL; | ||
2493 | 76 | static int stringmemorycount = 0; | ||
2494 | 77 | static const unsigned long stringmemblocksizekib = (unsigned long) sizeof(struct stringmemblock) / 1024; | ||
2495 | 78 | |||
2496 | 79 | char *my_strdup(char *foo) { | ||
2497 | 80 | struct stringmemblock *which; | ||
2498 | 81 | size_t len; | ||
2499 | 82 | |||
2500 | 83 | if (!foo) return NULL; | ||
2501 | 84 | |||
2502 | 85 | len = strlen(foo) + 1; | ||
2503 | 86 | |||
2504 | 87 | if (len > SMB_SIZE) return strdup(foo); | ||
2505 | 88 | |||
2506 | 89 | for (which = stringmemory; which; which = which->next) { | ||
2507 | 90 | if (SMB_SIZE - which->last > len + 1) { | ||
2508 | 91 | break; | ||
2509 | 92 | } | ||
2510 | 93 | } | ||
2511 | 94 | if (!which) { | ||
2512 | 95 | which = malloc(sizeof(struct stringmemblock)); | ||
2513 | 96 | if (!which) return NULL; | ||
2514 | 97 | MDEBUG1_ONLY(fprintf(stderr, | ||
2515 | 98 | "ALLOC: string memblock %d (%lu KiB, %lu KiB total)\n", | ||
2516 | 99 | stringmemorycount, stringmemblocksizekib, | ||
2517 | 100 | (stringmemorycount+1) * stringmemblocksizekib)); | ||
2518 | 101 | memset(which->mem, 0, SMB_SIZE); | ||
2519 | 102 | which->last = 0; | ||
2520 | 103 | which->next = stringmemory; | ||
2521 | 104 | stringmemory = which; | ||
2522 | 105 | stringmemorycount++; | ||
2523 | 106 | } | ||
2524 | 107 | strcpy(&which->mem[which->last], foo); | ||
2525 | 108 | foo = &which->mem[which->last]; | ||
2526 | 109 | which->last += len; | ||
2527 | 110 | return foo; | ||
2528 | 111 | } | ||
2529 | 112 | |||
2530 | 113 | char *my_rep_strdup(char *foo) { | ||
2531 | 114 | static char *repeats[1000] = {0}; | ||
2532 | 115 | int i; | ||
2533 | 116 | |||
2534 | 117 | for (i = 0; i < 1000; i++) { | ||
2535 | 118 | if (repeats[i] == NULL) { | ||
2536 | 119 | DEBUG_ONLY(fprintf(stderr, "REPEAT NR %d\n", i+1); ) | ||
2537 | 120 | return repeats[i] = my_strdup(foo); | ||
2538 | 121 | } | ||
2539 | 122 | if (strcmp(repeats[i], foo) == 0) return repeats[i]; | ||
2540 | 123 | } | ||
2541 | 124 | |||
2542 | 125 | return my_strdup(foo); | ||
2543 | 126 | } | ||
2544 | 127 | |||
2545 | 128 | /* DIE **/ | ||
2546 | 129 | |||
2547 | 130 | static void die(char *orig_msg) { | ||
2548 | 131 | char *msg = my_strdup(orig_msg); | ||
2549 | 132 | if (*msg && msg[strlen(msg)-1] == ':') { | ||
2550 | 133 | msg[strlen(msg)-1] = '\0'; | ||
2551 | 134 | perror(msg); | ||
2552 | 135 | } else { | ||
2553 | 136 | printf("%s\n", msg); | ||
2554 | 137 | } | ||
2555 | 138 | abort(); | ||
2556 | 139 | } | ||
2557 | 140 | |||
2558 | 141 | /************************************************************************* | ||
2559 | 142 | * Dpkg Control/Packages/etc Operations | ||
2560 | 143 | */ | ||
2561 | 144 | |||
2562 | 145 | static dpkg_paragraph *read_paragraph( FILE *f ) { | ||
2563 | 146 | dpkg_paragraph *result; | ||
2564 | 147 | static int line_size = 0; | ||
2565 | 148 | static char *line = NULL; | ||
2566 | 149 | char *pch; | ||
2567 | 150 | |||
2568 | 151 | dpkg_entry *c_entry = NULL; | ||
2569 | 152 | char *c_value = NULL; | ||
2570 | 153 | |||
2571 | 154 | if (line == NULL) { | ||
2572 | 155 | line_size = 10; | ||
2573 | 156 | line = malloc(line_size); | ||
2574 | 157 | if (line == NULL) die("read_paragraph alloc 0:"); | ||
2575 | 158 | } | ||
2576 | 159 | |||
2577 | 160 | result = block_malloc( sizeof(dpkg_paragraph) ); | ||
2578 | 161 | if (result == NULL) die("read_paragraph alloc 1:"); | ||
2579 | 162 | |||
2580 | 163 | result->n_entries = 0; | ||
2581 | 164 | result->entry = NULL; | ||
2582 | 165 | result->n_allocated = 0; | ||
2583 | 166 | |||
2584 | 167 | while(fgets(line, line_size, f)) { | ||
2585 | 168 | while (!feof(f) && *line && line[strlen(line)-1] != '\n') { | ||
2586 | 169 | line = realloc(line, line_size * 2); | ||
2587 | 170 | if (!line) die("read_paragraph realloc:"); | ||
2588 | 171 | fgets(line + strlen(line), line_size, f); | ||
2589 | 172 | line_size *= 2; | ||
2590 | 173 | } | ||
2591 | 174 | |||
2592 | 175 | if (line[0] == '\n') break; | ||
2593 | 176 | |||
2594 | 177 | if (isspace(line[0])) { | ||
2595 | 178 | if (c_value == NULL) | ||
2596 | 179 | die("read_paragraph early spaces"); | ||
2597 | 180 | |||
2598 | 181 | if (c_entry == NULL) { | ||
2599 | 182 | /* no need to bother */ | ||
2600 | 183 | } else { | ||
2601 | 184 | /* extend the line */ | ||
2602 | 185 | c_value = realloc(c_value, strlen(c_value) + strlen(line) + 1); | ||
2603 | 186 | if (c_value == NULL) | ||
2604 | 187 | die("read_paragraph realloc c_value:"); | ||
2605 | 188 | |||
2606 | 189 | strcat(c_value, line); | ||
2607 | 190 | } | ||
2608 | 191 | } else { | ||
2609 | 192 | if (c_entry) { | ||
2610 | 193 | c_entry->value = my_strdup(c_value); | ||
2611 | 194 | c_value[0] = '\0'; | ||
2612 | 195 | free(c_value); | ||
2613 | 196 | c_value = NULL; | ||
2614 | 197 | } else if (c_value) { | ||
2615 | 198 | free(c_value); | ||
2616 | 199 | c_value = NULL; | ||
2617 | 200 | } | ||
2618 | 201 | pch = strchr(line, ':'); | ||
2619 | 202 | if (pch == NULL) { | ||
2620 | 203 | fprintf(stderr, "the line was: \"%s\"\n", line); | ||
2621 | 204 | die("read_paragraph: no colon"); | ||
2622 | 205 | } | ||
2623 | 206 | |||
2624 | 207 | *pch = '\0'; | ||
2625 | 208 | while(isspace(*++pch)); | ||
2626 | 209 | |||
2627 | 210 | if (strcmp(line, "Description") == 0) { | ||
2628 | 211 | c_value = strdup(pch); | ||
2629 | 212 | c_entry = NULL; | ||
2630 | 213 | } else { | ||
2631 | 214 | assert(result->n_entries <= result->n_allocated); | ||
2632 | 215 | if (result->n_entries >= result->n_allocated) { | ||
2633 | 216 | result->n_allocated += 10; | ||
2634 | 217 | result->entry = realloc( result->entry, | ||
2635 | 218 | sizeof(dpkg_entry) | ||
2636 | 219 | * result->n_allocated); | ||
2637 | 220 | if (result->entry == NULL) | ||
2638 | 221 | die("read_paragraph realloc entry:"); | ||
2639 | 222 | } | ||
2640 | 223 | |||
2641 | 224 | c_entry = &result->entry[result->n_entries++]; | ||
2642 | 225 | c_entry->name = my_rep_strdup(line); | ||
2643 | 226 | c_value = strdup(pch); | ||
2644 | 227 | } | ||
2645 | 228 | } | ||
2646 | 229 | } | ||
2647 | 230 | |||
2648 | 231 | if (c_entry) { | ||
2649 | 232 | c_entry->value = my_strdup(c_value); | ||
2650 | 233 | c_value[0] = '\0'; | ||
2651 | 234 | free(c_value); | ||
2652 | 235 | c_value = NULL; | ||
2653 | 236 | } | ||
2654 | 237 | |||
2655 | 238 | if (result->n_entries == 0) { | ||
2656 | 239 | if (result->entry) free(result->entry); | ||
2657 | 240 | block_free(result, sizeof(dpkg_paragraph)); | ||
2658 | 241 | return NULL; | ||
2659 | 242 | } else { | ||
2660 | 243 | result->entry = realloc(result->entry, | ||
2661 | 244 | sizeof(result->entry[0]) * result->n_entries); | ||
2662 | 245 | result->n_allocated = result->n_entries; | ||
2663 | 246 | } | ||
2664 | 247 | |||
2665 | 248 | return result; | ||
2666 | 249 | } | ||
2667 | 250 | |||
2668 | 251 | static void write_paragraph(FILE *f, dpkg_paragraph *p) { | ||
2669 | 252 | int i; | ||
2670 | 253 | |||
2671 | 254 | for (i = 0; i < p->n_entries; i++) { | ||
2672 | 255 | fprintf(f, "%s: %s", p->entry[i].name, p->entry[i].value); | ||
2673 | 256 | } | ||
2674 | 257 | fprintf(f, "\n"); | ||
2675 | 258 | } | ||
2676 | 259 | |||
2677 | 260 | |||
2678 | 261 | static void free_paragraph(dpkg_paragraph *p) { | ||
2679 | 262 | int i; | ||
2680 | 263 | |||
2681 | 264 | if (p == NULL) return; | ||
2682 | 265 | |||
2683 | 266 | for (i = 0; i < p->n_entries; i++) { | ||
2684 | 267 | /* block_free(p->entry[i].name); */ | ||
2685 | 268 | /* block_free(p->entry[i].value); */ | ||
2686 | 269 | } | ||
2687 | 270 | free(p->entry); | ||
2688 | 271 | block_free(p, sizeof(dpkg_paragraph)); | ||
2689 | 272 | } | ||
2690 | 273 | |||
2691 | 274 | /************************************************************************* | ||
2692 | 275 | * Basic Package Operations | ||
2693 | 276 | */ | ||
2694 | 277 | |||
2695 | 278 | static dpkg_package *new_package(void) { | ||
2696 | 279 | dpkg_package *result; | ||
2697 | 280 | |||
2698 | 281 | result = block_malloc(sizeof(dpkg_package)); | ||
2699 | 282 | if (result == NULL) die("new_package alloc:"); | ||
2700 | 283 | |||
2701 | 284 | result->package = NULL; | ||
2702 | 285 | result->version = NULL; | ||
2703 | 286 | |||
2704 | 287 | result->priority = 0; | ||
2705 | 288 | result->arch_all = 0; | ||
2706 | 289 | |||
2707 | 290 | result->source = NULL; | ||
2708 | 291 | result->source_ver = NULL; | ||
2709 | 292 | |||
2710 | 293 | result->depends[0] = NULL; | ||
2711 | 294 | result->depends[1] = NULL; | ||
2712 | 295 | result->depends[2] = NULL; | ||
2713 | 296 | result->depends[3] = NULL; | ||
2714 | 297 | |||
2715 | 298 | result->conflicts = NULL; | ||
2716 | 299 | |||
2717 | 300 | result->provides = NULL; | ||
2718 | 301 | result->details = NULL; | ||
2719 | 302 | |||
2720 | 303 | return result; | ||
2721 | 304 | } | ||
2722 | 305 | |||
2723 | 306 | static dpkg_collected_package *new_collected_package(dpkg_package *pkg) { | ||
2724 | 307 | dpkg_collected_package *result; | ||
2725 | 308 | |||
2726 | 309 | result = block_malloc(sizeof(dpkg_collected_package)); | ||
2727 | 310 | if (result == NULL) die("new_collected_package alloc:"); | ||
2728 | 311 | |||
2729 | 312 | result->pkg = pkg; | ||
2730 | 313 | |||
2731 | 314 | result->installed = 0; | ||
2732 | 315 | result->conflicted = 0; | ||
2733 | 316 | |||
2734 | 317 | result->installable = UNKNOWN; | ||
2735 | 318 | result->mayaffect = NULL; | ||
2736 | 319 | |||
2737 | 320 | return result; | ||
2738 | 321 | } | ||
2739 | 322 | |||
2740 | 323 | static void free_collected_package(dpkg_collected_package *cpkg) { | ||
2741 | 324 | if (cpkg == NULL) return; | ||
2742 | 325 | cpkg->pkg = NULL; | ||
2743 | 326 | free_packagenamelist(cpkg->mayaffect); | ||
2744 | 327 | cpkg->mayaffect = NULL; | ||
2745 | 328 | block_free(cpkg, sizeof(dpkg_collected_package)); | ||
2746 | 329 | } | ||
2747 | 330 | |||
2748 | 331 | static void free_package(dpkg_package *pkg) { | ||
2749 | 332 | int i; | ||
2750 | 333 | if (pkg == NULL) return; | ||
2751 | 334 | |||
2752 | 335 | /* block_free(pkg->package); | ||
2753 | 336 | * block_free(pkg->version); | ||
2754 | 337 | * block_free(pkg->source); | ||
2755 | 338 | * block_free(pkg->source_ver); */ | ||
2756 | 339 | |||
2757 | 340 | for (i = 0; i < 4; i++) | ||
2758 | 341 | free_deplistlist(pkg->depends[i]); | ||
2759 | 342 | |||
2760 | 343 | free_deplist(pkg->conflicts); | ||
2761 | 344 | free_ownedpackagenamelist(pkg->provides); | ||
2762 | 345 | |||
2763 | 346 | free_paragraph(pkg->details); | ||
2764 | 347 | |||
2765 | 348 | block_free(pkg, sizeof(dpkg_package)); | ||
2766 | 349 | } | ||
2767 | 350 | |||
2768 | 351 | static dpkg_package *read_package( FILE *f ) { | ||
2769 | 352 | dpkg_package *result; | ||
2770 | 353 | dpkg_paragraph *para; | ||
2771 | 354 | dpkg_entry *e; | ||
2772 | 355 | int i; | ||
2773 | 356 | |||
2774 | 357 | para = read_paragraph(f); | ||
2775 | 358 | if (para == NULL) return NULL; | ||
2776 | 359 | |||
2777 | 360 | result = new_package(); | ||
2778 | 361 | result->details = para; | ||
2779 | 362 | |||
2780 | 363 | for (e = ¶->entry[0]; e < ¶->entry[para->n_entries]; e++) { | ||
2781 | 364 | if (strcasecmp("Package", e->name) == 0) { | ||
2782 | 365 | result->package = my_strdup(e->value); | ||
2783 | 366 | if (result->package == NULL) | ||
2784 | 367 | die("read_package my_strdup:"); | ||
2785 | 368 | result->package[strlen(result->package)-1] = '\0'; | ||
2786 | 369 | } | ||
2787 | 370 | |||
2788 | 371 | if (strcasecmp("Version", e->name) == 0) { | ||
2789 | 372 | result->version = my_strdup(e->value); | ||
2790 | 373 | if (result->version == NULL) | ||
2791 | 374 | die("read_package my_strdup:"); | ||
2792 | 375 | result->version[strlen(result->version)-1] = '\0'; | ||
2793 | 376 | } | ||
2794 | 377 | |||
2795 | 378 | if (strcasecmp("Priority", e->name) == 0) { | ||
2796 | 379 | int i; | ||
2797 | 380 | for (i = 0; priorities[i] != NULL; i++) { | ||
2798 | 381 | if (strcasecmp(priorities[i], e->value)) | ||
2799 | 382 | break; | ||
2800 | 383 | } | ||
2801 | 384 | result->priority = i; | ||
2802 | 385 | if (priorities[i] == NULL) { | ||
2803 | 386 | die("read_package: unknown priority"); | ||
2804 | 387 | } | ||
2805 | 388 | } | ||
2806 | 389 | |||
2807 | 390 | if (strcasecmp("Architecture", e->name) == 0) { | ||
2808 | 391 | if (strncasecmp(e->value, "all", 3) == 0) { | ||
2809 | 392 | if (!e->value[3] || isspace(e->value[3])) { | ||
2810 | 393 | result->arch_all = 1; | ||
2811 | 394 | } | ||
2812 | 395 | } | ||
2813 | 396 | } | ||
2814 | 397 | |||
2815 | 398 | for (i = 0; dependency_title[i] != NULL; i++) { | ||
2816 | 399 | if (strcasecmp(dependency_title[i], e->name) == 0) { | ||
2817 | 400 | result->depends[i] = read_dep_andor(e->value); | ||
2818 | 401 | } | ||
2819 | 402 | } | ||
2820 | 403 | |||
2821 | 404 | /* | ||
2822 | 405 | * Support Breaks by treating them as Conflicts. | ||
2823 | 406 | */ | ||
2824 | 407 | if (strcasecmp("Conflicts", e->name) == 0 | ||
2825 | 408 | || strcasecmp("Breaks", e->name) == 0) { | ||
2826 | 409 | deplist *pkgs = read_dep_and(e->value); | ||
2827 | 410 | if (result->conflicts == NULL) | ||
2828 | 411 | result->conflicts = pkgs; | ||
2829 | 412 | else { | ||
2830 | 413 | // TODO(dato): create extend_deplist() in templates.h? | ||
2831 | 414 | deplist *end = result->conflicts; | ||
2832 | 415 | while (end->next) | ||
2833 | 416 | end = end->next; | ||
2834 | 417 | end->next = pkgs; | ||
2835 | 418 | } | ||
2836 | 419 | } | ||
2837 | 420 | |||
2838 | 421 | if (strcasecmp("Provides", e->name) == 0) | ||
2839 | 422 | result->provides = read_packagenames(e->value); | ||
2840 | 423 | |||
2841 | 424 | if (strcasecmp("source", e->name) == 0) { | ||
2842 | 425 | char *pch = e->value; | ||
2843 | 426 | |||
2844 | 427 | assert(result->source == NULL); | ||
2845 | 428 | assert(result->source_ver == NULL); | ||
2846 | 429 | |||
2847 | 430 | result->source = my_strdup(read_packagename(&pch, "(")); | ||
2848 | 431 | if (result->source == NULL) | ||
2849 | 432 | die("read_package: bad source header"); | ||
2850 | 433 | |||
2851 | 434 | while(isspace(*pch)) pch++; | ||
2852 | 435 | if (*pch == '(') { | ||
2853 | 436 | pch++; | ||
2854 | 437 | result->source_ver = my_strdup(read_until_char(&pch, ")")); | ||
2855 | 438 | if (result->source_ver == NULL) | ||
2856 | 439 | die("read_package: bad source version"); | ||
2857 | 440 | while(isspace(*pch)) pch++; | ||
2858 | 441 | if (*pch != ')') | ||
2859 | 442 | die("read_package: unterminated ver"); | ||
2860 | 443 | } | ||
2861 | 444 | } | ||
2862 | 445 | } | ||
2863 | 446 | |||
2864 | 447 | if (result->source == NULL) { | ||
2865 | 448 | assert(result->source_ver == NULL); | ||
2866 | 449 | result->source = my_strdup(result->package); | ||
2867 | 450 | } | ||
2868 | 451 | if (result->source_ver == NULL) { | ||
2869 | 452 | result->source_ver = my_strdup(result->version); | ||
2870 | 453 | } | ||
2871 | 454 | |||
2872 | 455 | return result; | ||
2873 | 456 | } | ||
2874 | 457 | |||
2875 | 458 | static void freesize(void *p, size_t s) { (void)s; free(p); } | ||
2876 | 459 | |||
2877 | 460 | LIST_IMPL(deplist, dependency*, free_dependency, block_malloc, block_free); | ||
2878 | 461 | LIST_IMPL(deplistlist, deplist*, free_deplist, block_malloc, block_free); | ||
2879 | 462 | |||
2880 | 463 | LIST_IMPLX(packagenamelist, char*, KEEP(char*)); | ||
2881 | 464 | |||
2882 | 465 | LIST_IMPL(ownedpackagenamelist, char*, KEEP(char*), block_malloc, block_free); | ||
2883 | 466 | /* ownedpackagenamelist stores the packagename in the string store */ | ||
2884 | 467 | |||
2885 | 468 | static int packagecmp(dpkg_package *l, dpkg_package *r) { | ||
2886 | 469 | if (l->priority < r->priority) return -1; | ||
2887 | 470 | if (l->priority > r->priority) return +1; | ||
2888 | 471 | return strcmp(l->package, r->package); | ||
2889 | 472 | } | ||
2890 | 473 | |||
2891 | 474 | /* container for owned pkgs */ | ||
2892 | 475 | LIST_IMPL(ownedpackagelist, dpkg_package *, free_package, | ||
2893 | 476 | block_malloc, block_free); | ||
2894 | 477 | |||
2895 | 478 | /* container for existing pkgs */ | ||
2896 | 479 | LIST_IMPL(packagelist, dpkg_package *, KEEP(dpkg_package *), block_malloc, block_free); | ||
2897 | 480 | |||
2898 | 481 | LIST_IMPLX(collpackagelist, dpkg_collected_package *, | ||
2899 | 482 | KEEP(dpkg_collected_package *)) | ||
2900 | 483 | #define insert_collpackagelist(x,y) insert_l_collpackagelist(x,y,__LINE__) | ||
2901 | 484 | |||
2902 | 485 | /************************************************************************* | ||
2903 | 486 | * Operations on distributions (collections of packages) | ||
2904 | 487 | */ | ||
2905 | 488 | |||
2906 | 489 | dpkg_packages *new_packages(char *arch) { | ||
2907 | 490 | dpkg_packages *result; | ||
2908 | 491 | |||
2909 | 492 | result = block_malloc(sizeof(dpkg_packages)); | ||
2910 | 493 | if (result == NULL) die("new_packages alloc:"); | ||
2911 | 494 | |||
2912 | 495 | result->arch = my_strdup(arch); | ||
2913 | 496 | result->packages = new_packagetbl(); | ||
2914 | 497 | result->virtualpkgs = new_virtualpkgtbl(); | ||
2915 | 498 | |||
2916 | 499 | return result; | ||
2917 | 500 | } | ||
2918 | 501 | |||
2919 | 502 | static void add_package(dpkg_packages *pkgs, dpkg_package *pkg) | ||
2920 | 503 | { | ||
2921 | 504 | ownedpackagenamelist *v; | ||
2922 | 505 | dpkg_collected_package *cpkg; | ||
2923 | 506 | |||
2924 | 507 | if (lookup_packagetbl(pkgs->packages, pkg->package) != NULL) | ||
2925 | 508 | return; | ||
2926 | 509 | |||
2927 | 510 | cpkg = new_collected_package(pkg); | ||
2928 | 511 | |||
2929 | 512 | add_packagetbl(pkgs->packages, cpkg->pkg->package, cpkg); | ||
2930 | 513 | |||
2931 | 514 | add_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package, | ||
2932 | 515 | cpkg->pkg->version, cpkg); | ||
2933 | 516 | for (v = cpkg->pkg->provides; v != NULL; v = v->next) { | ||
2934 | 517 | add_virtualpackage(pkgs->virtualpkgs, v->value, NULL, cpkg); | ||
2935 | 518 | } | ||
2936 | 519 | } | ||
2937 | 520 | |||
2938 | 521 | static void remove_package(dpkg_packages *pkgs, dpkg_collected_package *cpkg) { | ||
2939 | 522 | ownedpackagenamelist *v; | ||
2940 | 523 | packagenamelist *aff; | ||
2941 | 524 | dpkg_collected_package *p; | ||
2942 | 525 | |||
2943 | 526 | for (aff = cpkg->mayaffect; aff != NULL; aff = aff->next) { | ||
2944 | 527 | p = lookup_packagetbl(pkgs->packages, aff->value); | ||
2945 | 528 | if (p == NULL) continue; | ||
2946 | 529 | p->installable = UNKNOWN; | ||
2947 | 530 | } | ||
2948 | 531 | |||
2949 | 532 | p = remove_packagetbl(pkgs->packages, cpkg->pkg->package); | ||
2950 | 533 | if (p != cpkg) return; | ||
2951 | 534 | |||
2952 | 535 | remove_virtualpackage(pkgs->virtualpkgs, cpkg->pkg->package, cpkg); | ||
2953 | 536 | for (v = cpkg->pkg->provides; v != NULL; v = v->next) { | ||
2954 | 537 | remove_virtualpackage(pkgs->virtualpkgs, v->value, cpkg); | ||
2955 | 538 | } | ||
2956 | 539 | |||
2957 | 540 | free_collected_package(cpkg); | ||
2958 | 541 | } | ||
2959 | 542 | |||
2960 | 543 | dpkg_packages *get_architecture(dpkg_sources *srcs, char *arch) { | ||
2961 | 544 | int i, arch_index; | ||
2962 | 545 | dpkg_packages *result; | ||
2963 | 546 | sourcetbl_iter srci; | ||
2964 | 547 | ownedpackagelist *p; | ||
2965 | 548 | |||
2966 | 549 | arch_index = -1; | ||
2967 | 550 | for (i = 0; i < srcs->n_arches; i++) { | ||
2968 | 551 | if (strcmp(srcs->archname[i], arch) == 0) { | ||
2969 | 552 | arch_index = i; | ||
2970 | 553 | break; | ||
2971 | 554 | } | ||
2972 | 555 | } | ||
2973 | 556 | if (arch_index == -1) die("get_architecture: unknown arch"); | ||
2974 | 557 | |||
2975 | 558 | result = new_packages(arch); | ||
2976 | 559 | |||
2977 | 560 | for (srci = first_sourcetbl(srcs->sources); | ||
2978 | 561 | !done_sourcetbl(srci); | ||
2979 | 562 | srci = next_sourcetbl(srci)) | ||
2980 | 563 | { | ||
2981 | 564 | for (p = srci.v->packages[arch_index]; p != NULL; p = p->next) { | ||
2982 | 565 | add_package(result, p->value); | ||
2983 | 566 | } | ||
2984 | 567 | } | ||
2985 | 568 | |||
2986 | 569 | return result; | ||
2987 | 570 | } | ||
2988 | 571 | |||
2989 | 572 | void free_packages(dpkg_packages *pkgs) { | ||
2990 | 573 | if (pkgs == NULL) return; | ||
2991 | 574 | /* block_free(pkgs->arch); */ | ||
2992 | 575 | free_packagetbl(pkgs->packages); | ||
2993 | 576 | free_virtualpkgtbl(pkgs->virtualpkgs); | ||
2994 | 577 | block_free(pkgs, sizeof(dpkg_packages)); | ||
2995 | 578 | } | ||
2996 | 579 | |||
2997 | 580 | |||
2998 | 581 | HASH_IMPL(packagetbl, char *, dpkg_collected_package *, SIZEOFHASHMAP, strhash, strcmp, | ||
2999 | 582 | KEEP(char*),free_collected_package); | ||
3000 | 583 | HASH_IMPL(virtualpkgtbl, char *, virtualpkg *, SIZEOFHASHMAP, strhash, strcmp, | ||
3001 | 584 | KEEP(char*), free_virtualpkg); | ||
3002 | 585 | |||
3003 | 586 | /* dpkg_provision refers to memory allocated elsewhere */ | ||
3004 | 587 | LIST_IMPL(virtualpkg, dpkg_provision, KEEP(dpkg_provision), block_malloc, block_free); | ||
3005 | 588 | |||
3006 | 589 | static void remove_virtualpackage(virtualpkgtbl *vpkgs, char *pkgname, | ||
3007 | 590 | dpkg_collected_package *cpkg) | ||
3008 | 591 | { | ||
3009 | 592 | virtualpkg *list; | ||
3010 | 593 | virtualpkg **where; | ||
3011 | 594 | list = lookup_virtualpkgtbl(vpkgs, pkgname); | ||
3012 | 595 | assert(list != NULL); | ||
3013 | 596 | |||
3014 | 597 | where = &list; | ||
3015 | 598 | while((*where)->value.pkg != cpkg) { | ||
3016 | 599 | where = &(*where)->next; | ||
3017 | 600 | assert(*where != NULL); | ||
3018 | 601 | } | ||
3019 | 602 | |||
3020 | 603 | delete_virtualpkg(where); | ||
3021 | 604 | |||
3022 | 605 | if (list == NULL) { | ||
3023 | 606 | remove_virtualpkgtbl(vpkgs, pkgname); | ||
3024 | 607 | } else { | ||
3025 | 608 | replace_virtualpkgtbl(vpkgs, pkgname, list); | ||
3026 | 609 | } | ||
3027 | 610 | } | ||
3028 | 611 | |||
3029 | 612 | static void add_virtualpackage(virtualpkgtbl *vpkgs, char *package, | ||
3030 | 613 | char *version, dpkg_collected_package *cpkg) | ||
3031 | 614 | { | ||
3032 | 615 | dpkg_provision value; | ||
3033 | 616 | virtualpkg *list, **addto; | ||
3034 | 617 | int shouldreplace; | ||
3035 | 618 | |||
3036 | 619 | value.pkg = cpkg; | ||
3037 | 620 | value.version = version; | ||
3038 | 621 | |||
3039 | 622 | list = lookup_virtualpkgtbl(vpkgs, package); | ||
3040 | 623 | shouldreplace = (list != NULL); | ||
3041 | 624 | |||
3042 | 625 | addto = &list; | ||
3043 | 626 | while (*addto != NULL | ||
3044 | 627 | && packagecmp(cpkg->pkg, (*addto)->value.pkg->pkg) >= 0) | ||
3045 | 628 | { | ||
3046 | 629 | addto = &(*addto)->next; | ||
3047 | 630 | } | ||
3048 | 631 | insert_virtualpkg(addto, value); | ||
3049 | 632 | |||
3050 | 633 | if (shouldreplace) { | ||
3051 | 634 | replace_virtualpkgtbl(vpkgs, package, list); | ||
3052 | 635 | /* old list is included in new list, so we don't need to free */ | ||
3053 | 636 | } else { | ||
3054 | 637 | add_virtualpkgtbl(vpkgs, package, list); | ||
3055 | 638 | } | ||
3056 | 639 | } | ||
3057 | 640 | |||
3058 | 641 | /************************************************************************* | ||
3059 | 642 | * Parsing Helper Functions | ||
3060 | 643 | */ | ||
3061 | 644 | |||
3062 | 645 | static ownedpackagenamelist *read_packagenames(char *buf) { | ||
3063 | 646 | ownedpackagenamelist *result = NULL; | ||
3064 | 647 | ownedpackagenamelist **addto = &result; | ||
3065 | 648 | |||
3066 | 649 | DEBUG_ONLY( char *strend = buf + strlen(buf); ) | ||
3067 | 650 | |||
3068 | 651 | char *sub; | ||
3069 | 652 | |||
3070 | 653 | while ((sub = my_strdup(read_packagename(&buf, ",")))) { | ||
3071 | 654 | insert_ownedpackagenamelist(addto, sub); | ||
3072 | 655 | addto = &(*addto)->next; | ||
3073 | 656 | |||
3074 | 657 | while(isspace(*buf)) buf++; | ||
3075 | 658 | if (*buf == ',') { | ||
3076 | 659 | buf++; | ||
3077 | 660 | continue; | ||
3078 | 661 | } | ||
3079 | 662 | if (*buf == '\0') { | ||
3080 | 663 | break; | ||
3081 | 664 | } | ||
3082 | 665 | |||
3083 | 666 | die("read_packagenames no/bad seperator"); | ||
3084 | 667 | } | ||
3085 | 668 | |||
3086 | 669 | DEBUG_ONLY( assert(buf <= strend); ) | ||
3087 | 670 | |||
3088 | 671 | return result; | ||
3089 | 672 | } | ||
3090 | 673 | |||
3091 | 674 | static char *read_until_char(char **buf, char *end) { | ||
3092 | 675 | static char *result = NULL; | ||
3093 | 676 | char *start; | ||
3094 | 677 | DEBUG_ONLY( char *strend = *buf + strlen(*buf); ) | ||
3095 | 678 | int n; | ||
3096 | 679 | |||
3097 | 680 | while(isspace(**buf)) (*buf)++; | ||
3098 | 681 | |||
3099 | 682 | start = *buf; | ||
3100 | 683 | while (**buf && !isspace(**buf) && strchr(end, **buf) == NULL) { | ||
3101 | 684 | (*buf)++; | ||
3102 | 685 | } | ||
3103 | 686 | |||
3104 | 687 | n = *buf - start; | ||
3105 | 688 | if (n == 0) return NULL; | ||
3106 | 689 | |||
3107 | 690 | result = realloc(result, n + 1); | ||
3108 | 691 | if (result == NULL) die("read_until_char alloc:"); | ||
3109 | 692 | |||
3110 | 693 | strncpy(result, start, n); | ||
3111 | 694 | result[n] = '\0'; | ||
3112 | 695 | |||
3113 | 696 | while(isspace(**buf)) (*buf)++; | ||
3114 | 697 | |||
3115 | 698 | DEBUG_ONLY( assert(*buf <= strend); ) | ||
3116 | 699 | |||
3117 | 700 | return result; | ||
3118 | 701 | } | ||
3119 | 702 | |||
3120 | 703 | static char *read_packagename(char **buf, char *end) { | ||
3121 | 704 | return read_until_char(buf, end); | ||
3122 | 705 | } | ||
3123 | 706 | |||
3124 | 707 | static deplist *read_dep_and(char *buf) { | ||
3125 | 708 | return read_deplist(&buf, ',', '\0'); | ||
3126 | 709 | } | ||
3127 | 710 | |||
3128 | 711 | static deplist *read_deplist(char **buf, char sep, char end) { | ||
3129 | 712 | deplist *result = NULL; | ||
3130 | 713 | deplist **addto = &result; | ||
3131 | 714 | |||
3132 | 715 | char separs[3] = { sep, end, '\0' }; | ||
3133 | 716 | |||
3134 | 717 | DEBUG_ONLY( char *strend = *buf + strlen(*buf); ) | ||
3135 | 718 | |||
3136 | 719 | dependency *sub; | ||
3137 | 720 | |||
3138 | 721 | while ((sub = read_dependency(buf, separs))) { | ||
3139 | 722 | insert_deplist(addto, sub); | ||
3140 | 723 | addto = &(*addto)->next; | ||
3141 | 724 | |||
3142 | 725 | while(isspace(**buf)) (*buf)++; | ||
3143 | 726 | if (**buf == sep) { | ||
3144 | 727 | (*buf)++; | ||
3145 | 728 | continue; | ||
3146 | 729 | } | ||
3147 | 730 | if (**buf == '\0' || **buf == end) { | ||
3148 | 731 | break; | ||
3149 | 732 | } | ||
3150 | 733 | |||
3151 | 734 | die("read_deplist no/bad seperator"); | ||
3152 | 735 | } | ||
3153 | 736 | |||
3154 | 737 | DEBUG_ONLY( assert(*buf <= strend); ) | ||
3155 | 738 | |||
3156 | 739 | return result; | ||
3157 | 740 | } | ||
3158 | 741 | |||
3159 | 742 | static deplistlist *read_dep_andor(char *buf) { | ||
3160 | 743 | deplistlist *result = NULL; | ||
3161 | 744 | deplistlist **addto = &result; | ||
3162 | 745 | |||
3163 | 746 | deplist *sub; | ||
3164 | 747 | |||
3165 | 748 | DEBUG_ONLY( char *strend = buf + strlen(buf); ) | ||
3166 | 749 | |||
3167 | 750 | while ((sub = read_deplist(&buf, '|', ','))) { | ||
3168 | 751 | insert_deplistlist(addto, sub); | ||
3169 | 752 | addto = &(*addto)->next; | ||
3170 | 753 | |||
3171 | 754 | if (*buf == ',') buf++; | ||
3172 | 755 | } | ||
3173 | 756 | |||
3174 | 757 | DEBUG_ONLY( assert(buf <= strend); ) | ||
3175 | 758 | |||
3176 | 759 | return result; | ||
3177 | 760 | } | ||
3178 | 761 | |||
3179 | 762 | static dependency *read_dependency(char **buf, char *end) { | ||
3180 | 763 | dependency *dep; | ||
3181 | 764 | char *name; | ||
3182 | 765 | char newend[10]; | ||
3183 | 766 | DEBUG_ONLY( char *strend = *buf + strlen(*buf); ) | ||
3184 | 767 | |||
3185 | 768 | assert(strlen(end) <= 8); | ||
3186 | 769 | newend[0] = '('; strcpy(newend + 1, end); | ||
3187 | 770 | |||
3188 | 771 | name = my_strdup(read_until_char(buf, newend)); | ||
3189 | 772 | if (name == NULL) return NULL; | ||
3190 | 773 | |||
3191 | 774 | dep = block_malloc(sizeof(dependency)); | ||
3192 | 775 | if (dep == NULL) die("read_dependency alloc 1:"); | ||
3193 | 776 | |||
3194 | 777 | dep->package = name; | ||
3195 | 778 | |||
3196 | 779 | while(isspace(**buf)) (*buf)++; | ||
3197 | 780 | |||
3198 | 781 | if (**buf != '(') { | ||
3199 | 782 | dep->op = dr_NOOP; | ||
3200 | 783 | dep->version = NULL; | ||
3201 | 784 | } else { | ||
3202 | 785 | (*buf)++; | ||
3203 | 786 | while(isspace(**buf)) (*buf)++; | ||
3204 | 787 | /* << , <= , = , >= , >> */ | ||
3205 | 788 | if (**buf == '<') { | ||
3206 | 789 | (*buf)++; | ||
3207 | 790 | if (**buf == '<') { | ||
3208 | 791 | dep->op = dr_LT; | ||
3209 | 792 | (*buf)++; | ||
3210 | 793 | } else if (**buf == '=') { | ||
3211 | 794 | dep->op = dr_LTEQ; | ||
3212 | 795 | (*buf)++; | ||
3213 | 796 | } else { | ||
3214 | 797 | /* The forms `<' and `>' were used to mean earlier/later or | ||
3215 | 798 | * equal, rather than strictly earlier/later, so they should | ||
3216 | 799 | * not appear in new packages (though `dpkg' still supports | ||
3217 | 800 | * them). | ||
3218 | 801 | */ | ||
3219 | 802 | dep->op = dr_LTEQ; | ||
3220 | 803 | } | ||
3221 | 804 | } else if (**buf == '>') { | ||
3222 | 805 | (*buf)++; | ||
3223 | 806 | if (**buf == '>') { | ||
3224 | 807 | dep->op = dr_GT; | ||
3225 | 808 | (*buf)++; | ||
3226 | 809 | } else if (**buf == '=') { | ||
3227 | 810 | dep->op = dr_GTEQ; | ||
3228 | 811 | (*buf)++; | ||
3229 | 812 | } else { | ||
3230 | 813 | dep->op = dr_GTEQ; | ||
3231 | 814 | } | ||
3232 | 815 | } else if (**buf == '=') { | ||
3233 | 816 | dep->op = dr_EQ; | ||
3234 | 817 | (*buf)++; | ||
3235 | 818 | if (**buf == '>') { | ||
3236 | 819 | dep->op = dr_GTEQ; | ||
3237 | 820 | (*buf)++; | ||
3238 | 821 | } else if (**buf == '<') { | ||
3239 | 822 | dep->op = dr_LTEQ; | ||
3240 | 823 | (*buf)++; | ||
3241 | 824 | } | ||
3242 | 825 | } else { | ||
3243 | 826 | /* treat it as an implicit = :( */ | ||
3244 | 827 | dep->op = dr_EQ; | ||
3245 | 828 | /* would prefer to: die("read_dependency unknown version op"); */ | ||
3246 | 829 | } | ||
3247 | 830 | |||
3248 | 831 | while (isspace(**buf)) (*buf)++; | ||
3249 | 832 | newend[0] = ')'; | ||
3250 | 833 | dep->version = my_strdup(read_until_char(buf, newend)); | ||
3251 | 834 | while (isspace(**buf)) (*buf)++; | ||
3252 | 835 | |||
3253 | 836 | if (dep->version == NULL) die("read_dependency: no version"); | ||
3254 | 837 | if (**buf != ')') die("read_dependency: unterminated version"); | ||
3255 | 838 | (*buf)++; | ||
3256 | 839 | } | ||
3257 | 840 | |||
3258 | 841 | DEBUG_ONLY( assert(*buf <= strend); ) | ||
3259 | 842 | |||
3260 | 843 | return dep; | ||
3261 | 844 | } | ||
3262 | 845 | |||
3263 | 846 | static void free_dependency(dependency *dep) { | ||
3264 | 847 | if (dep == NULL) return; | ||
3265 | 848 | /* block_free(dep->package); */ | ||
3266 | 849 | /* if (dep->version) block_free(dep->version); */ | ||
3267 | 850 | block_free(dep, sizeof(dependency)); | ||
3268 | 851 | } | ||
3269 | 852 | |||
3270 | 853 | /************************************************************************* | ||
3271 | 854 | * Installability Checking | ||
3272 | 855 | */ | ||
3273 | 856 | |||
3274 | 857 | static collpackagelist **get_matching_low(collpackagelist **addto, | ||
3275 | 858 | dpkg_packages *pkgs, dependency *dep, int line) | ||
3276 | 859 | { | ||
3277 | 860 | virtualpkg *vpkg; | ||
3278 | 861 | for (vpkg = lookup_virtualpkgtbl(pkgs->virtualpkgs, dep->package); | ||
3279 | 862 | vpkg != NULL; | ||
3280 | 863 | vpkg = vpkg->next) | ||
3281 | 864 | { | ||
3282 | 865 | int add; | ||
3283 | 866 | |||
3284 | 867 | add = 0; | ||
3285 | 868 | if (dep->op == dr_NOOP) { | ||
3286 | 869 | add = 1; | ||
3287 | 870 | } else if (vpkg->value.version != NULL) { | ||
3288 | 871 | if (cmpversions(vpkg->value.version, dep->op, dep->version)) { | ||
3289 | 872 | add = 1; | ||
3290 | 873 | } | ||
3291 | 874 | } | ||
3292 | 875 | |||
3293 | 876 | if (add) { | ||
3294 | 877 | insert_l_collpackagelist(addto, vpkg->value.pkg, line); | ||
3295 | 878 | addto = &(*addto)->next; | ||
3296 | 879 | } | ||
3297 | 880 | } | ||
3298 | 881 | |||
3299 | 882 | return addto; | ||
3300 | 883 | } | ||
3301 | 884 | |||
3302 | 885 | static collpackagelist *get_matching(dpkg_packages *pkgs, deplist *depopts, int line) { | ||
3303 | 886 | collpackagelist *list = NULL; | ||
3304 | 887 | collpackagelist **addto = &list; | ||
3305 | 888 | |||
3306 | 889 | for(; depopts != NULL; depopts = depopts->next) { | ||
3307 | 890 | addto = get_matching_low(addto, pkgs, depopts->value, line); | ||
3308 | 891 | } | ||
3309 | 892 | |||
3310 | 893 | return list; | ||
3311 | 894 | } | ||
3312 | 895 | |||
3313 | 896 | typedef struct instonelist instonelist; | ||
3314 | 897 | struct instonelist { | ||
3315 | 898 | collpackagelist *curX; | ||
3316 | 899 | collpackagelist *instoneX; | ||
3317 | 900 | int expandedX; | ||
3318 | 901 | struct instonelist *nextX, *prevX, *cutoffX; | ||
3319 | 902 | }; | ||
3320 | 903 | |||
3321 | 904 | #define I1CUR(i1) ((i1)->curX) | ||
3322 | 905 | #define I1INSTONE(i1) ((i1)->instoneX) | ||
3323 | 906 | #define I1CUTOFF(i1) ((i1)->cutoffX) | ||
3324 | 907 | #define I1NEXT(i1) ((i1)->nextX) /* can be modified ! */ | ||
3325 | 908 | #define I1PREV(i1) ((i1)->prevX) | ||
3326 | 909 | #define I1EXPANDED(i1) ((i1)->expandedX) | ||
3327 | 910 | |||
3328 | 911 | static instonelist *insert_instonelist(instonelist *where, collpackagelist *instone); | ||
3329 | 912 | static void trim_instonelist_after(instonelist *first); | ||
3330 | 913 | static void free_instonelist(instonelist *l); | ||
3331 | 914 | |||
3332 | 915 | static int max_instone_len = 0; | ||
3333 | 916 | static int cur_instone_len = 0; | ||
3334 | 917 | |||
3335 | 918 | static instonelist *insert_instonelist(instonelist *old, collpackagelist *instone) | ||
3336 | 919 | { | ||
3337 | 920 | instonelist *n = block_malloc(sizeof(instonelist)); | ||
3338 | 921 | if (n == NULL) | ||
3339 | 922 | die("insert_instonelist alloc:"); | ||
3340 | 923 | |||
3341 | 924 | n->curX = NULL; | ||
3342 | 925 | n->instoneX = instone; | ||
3343 | 926 | n->cutoffX = NULL; | ||
3344 | 927 | n->nextX = (old ? old->nextX : NULL); | ||
3345 | 928 | n->prevX = old; | ||
3346 | 929 | n->expandedX = 0; | ||
3347 | 930 | |||
3348 | 931 | if (old) old->nextX = n; | ||
3349 | 932 | if (n->nextX) n->nextX->prevX = n; | ||
3350 | 933 | |||
3351 | 934 | cur_instone_len++; | ||
3352 | 935 | if (cur_instone_len > max_instone_len) max_instone_len = cur_instone_len; | ||
3353 | 936 | |||
3354 | 937 | return n; | ||
3355 | 938 | } | ||
3356 | 939 | |||
3357 | 940 | static void trim_instonelist_after(instonelist *first) { | ||
3358 | 941 | if (!first->nextX) return; | ||
3359 | 942 | first->nextX->prevX = NULL; | ||
3360 | 943 | free_instonelist(first->nextX); | ||
3361 | 944 | first->nextX = NULL; | ||
3362 | 945 | } | ||
3363 | 946 | |||
3364 | 947 | static void free_instonelist(instonelist *l) { | ||
3365 | 948 | instonelist *p, *k; | ||
3366 | 949 | if (!l) return; | ||
3367 | 950 | for (p = l; p->nextX; p = p->nextX); | ||
3368 | 951 | do { | ||
3369 | 952 | k = p; | ||
3370 | 953 | p = k->prevX; | ||
3371 | 954 | free_collpackagelist(k->instoneX); | ||
3372 | 955 | block_free(k, sizeof(instonelist)); | ||
3373 | 956 | cur_instone_len--; | ||
3374 | 957 | } while (k != l); | ||
3375 | 958 | } | ||
3376 | 959 | |||
3377 | 960 | static int caninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) { | ||
3378 | 961 | collpackagelist *conflicts; | ||
3379 | 962 | collpackagelist *conf; | ||
3380 | 963 | int okay; | ||
3381 | 964 | |||
3382 | 965 | if (cpkg->installed > 0) return 1; | ||
3383 | 966 | if (cpkg->conflicted > 0) return 0; | ||
3384 | 967 | |||
3385 | 968 | conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__); | ||
3386 | 969 | |||
3387 | 970 | okay = 1; | ||
3388 | 971 | for (conf = conflicts; conf != NULL; conf = conf->next) { | ||
3389 | 972 | if (conf->value->installed > 0) { | ||
3390 | 973 | okay = 0; | ||
3391 | 974 | break; | ||
3392 | 975 | } | ||
3393 | 976 | } | ||
3394 | 977 | free_collpackagelist(conflicts); | ||
3395 | 978 | return okay; | ||
3396 | 979 | } | ||
3397 | 980 | |||
3398 | 981 | static int cur_install =0; | ||
3399 | 982 | static int max_install = 0; | ||
3400 | 983 | static int cur_conflicted = 0; | ||
3401 | 984 | static int max_conflicted = 0; | ||
3402 | 985 | |||
3403 | 986 | static void install(dpkg_packages *pkgs, dpkg_collected_package *cpkg) { | ||
3404 | 987 | if (cpkg->installed == 0) { | ||
3405 | 988 | collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__); | ||
3406 | 989 | collpackagelist *conf; | ||
3407 | 990 | for (conf = conflicts; conf != NULL; conf = conf->next) { | ||
3408 | 991 | if (conf->value == cpkg) continue; | ||
3409 | 992 | assert(conf->value->installed == 0); | ||
3410 | 993 | conf->value->conflicted++; | ||
3411 | 994 | if (conf->value->conflicted == 1) { | ||
3412 | 995 | cur_conflicted++; | ||
3413 | 996 | if (max_conflicted < cur_conflicted) | ||
3414 | 997 | max_conflicted = cur_conflicted; | ||
3415 | 998 | } | ||
3416 | 999 | } | ||
3417 | 1000 | free_collpackagelist(conflicts); | ||
3418 | 1001 | cur_install++; | ||
3419 | 1002 | if (max_install < cur_install) max_install = cur_install; | ||
3420 | 1003 | } | ||
3421 | 1004 | assert(cpkg->conflicted == 0); | ||
3422 | 1005 | cpkg->installed++; | ||
3423 | 1006 | } | ||
3424 | 1007 | |||
3425 | 1008 | static void uninstall(dpkg_packages *pkgs, dpkg_collected_package *cpkg) { | ||
3426 | 1009 | assert(cpkg->installed > 0); | ||
3427 | 1010 | assert(cpkg->conflicted == 0); | ||
3428 | 1011 | cpkg->installed--; | ||
3429 | 1012 | if (cpkg->installed == 0) { | ||
3430 | 1013 | collpackagelist *conflicts = get_matching(pkgs, cpkg->pkg->conflicts, __LINE__); | ||
3431 | 1014 | collpackagelist *conf; | ||
3432 | 1015 | for (conf = conflicts; conf != NULL; conf = conf->next) { | ||
3433 | 1016 | if (conf->value == cpkg) continue; | ||
3434 | 1017 | assert(conf->value->installed == 0); | ||
3435 | 1018 | assert(conf->value->conflicted > 0); | ||
3436 | 1019 | conf->value->conflicted--; | ||
3437 | 1020 | if (conf->value->conflicted == 0) cur_conflicted--; | ||
3438 | 1021 | } | ||
3439 | 1022 | free_collpackagelist(conflicts); | ||
3440 | 1023 | cur_install--; | ||
3441 | 1024 | } | ||
3442 | 1025 | } | ||
3443 | 1026 | |||
3444 | 1027 | satisfieddep *new_satisfieddep(void) { | ||
3445 | 1028 | satisfieddep *sd = block_malloc(sizeof(satisfieddep)); | ||
3446 | 1029 | if (!sd) die("new_satisfieddep alloc:"); | ||
3447 | 1030 | return sd; | ||
3448 | 1031 | } | ||
3449 | 1032 | |||
3450 | 1033 | void free_satisfieddep(satisfieddep *sd) { | ||
3451 | 1034 | if (!sd) return; | ||
3452 | 1035 | free_packagelist(sd->pkgs); | ||
3453 | 1036 | block_free(sd, sizeof(satisfieddep)); | ||
3454 | 1037 | } | ||
3455 | 1038 | |||
3456 | 1039 | LIST_IMPL(satisfieddeplist, satisfieddep *, free_satisfieddep, block_malloc, block_free); | ||
3457 | 1040 | |||
3458 | 1041 | packagelist *collpkglist2pkglist(collpackagelist *l) { | ||
3459 | 1042 | packagelist *r = NULL; | ||
3460 | 1043 | packagelist **addto = &r; | ||
3461 | 1044 | |||
3462 | 1045 | for (; l != NULL; l = l->next) { | ||
3463 | 1046 | insert_packagelist(addto, l->value->pkg); | ||
3464 | 1047 | addto = &(*addto)->next; | ||
3465 | 1048 | } | ||
3466 | 1049 | |||
3467 | 1050 | return r; | ||
3468 | 1051 | } | ||
3469 | 1052 | |||
3470 | 1053 | satisfieddeplist *checkunsatisfiabledeps(dpkg_packages *pkgs, | ||
3471 | 1054 | deplistlist *deps) { | ||
3472 | 1055 | satisfieddeplist *unsatisfiable = NULL; | ||
3473 | 1056 | satisfieddeplist **addto = &unsatisfiable; | ||
3474 | 1057 | satisfieddep *sd; | ||
3475 | 1058 | collpackagelist *deppkgs; | ||
3476 | 1059 | |||
3477 | 1060 | for (; deps != NULL; deps = deps->next) { | ||
3478 | 1061 | /* deplist *dep; */ | ||
3479 | 1062 | /* for (dep = deps->value; dep != NULL; dep = dep->next) { */ | ||
3480 | 1063 | sd = new_satisfieddep(); | ||
3481 | 1064 | /* sd->dep = dep->value; */ | ||
3482 | 1065 | sd->depl = deps->value; | ||
3483 | 1066 | |||
3484 | 1067 | deppkgs = NULL; | ||
3485 | 1068 | /* get_matching_low(&deppkgs, pkgs, dep->value); */ | ||
3486 | 1069 | deppkgs = get_matching(pkgs, deps->value, __LINE__); | ||
3487 | 1070 | sd->pkgs = collpkglist2pkglist(deppkgs); | ||
3488 | 1071 | free_collpackagelist(deppkgs); | ||
3489 | 1072 | |||
3490 | 1073 | insert_satisfieddeplist(addto, sd); | ||
3491 | 1074 | addto = &(*addto)->next; | ||
3492 | 1075 | /* } */ | ||
3493 | 1076 | } | ||
3494 | 1077 | |||
3495 | 1078 | return unsatisfiable; | ||
3496 | 1079 | } | ||
3497 | 1080 | |||
3498 | 1081 | int checkinstallable2(dpkg_packages *pkgs, char *pkgname) { | ||
3499 | 1082 | dpkg_collected_package *cpkg = lookup_packagetbl(pkgs->packages, pkgname); | ||
3500 | 1083 | collpackagelist *cpl = NULL; | ||
3501 | 1084 | |||
3502 | 1085 | if (cpkg == NULL) return 0; | ||
3503 | 1086 | |||
3504 | 1087 | insert_collpackagelist(&cpl, cpkg); | ||
3505 | 1088 | /* cpl gets freed in checkinstallable :-/ */ | ||
3506 | 1089 | return checkinstallable(pkgs, cpl); | ||
3507 | 1090 | } | ||
3508 | 1091 | |||
3509 | 1092 | static void debug_checkinstallable(FILE *out, instonelist *list, | ||
3510 | 1093 | instonelist *last, instonelist *pointer) | ||
3511 | 1094 | { | ||
3512 | 1095 | instonelist *l; | ||
3513 | 1096 | fprintf(out, "Status:"); | ||
3514 | 1097 | |||
3515 | 1098 | /* codes: | = multiple options here | ||
3516 | 1099 | * @ = no options can satisfy this dep | ||
3517 | 1100 | * + = dependencies that can be expanded have been | ||
3518 | 1101 | * * = nothing selected yet | ||
3519 | 1102 | * > = where pointer points | ||
3520 | 1103 | * ^ = the cut point for where we are | ||
3521 | 1104 | */ | ||
3522 | 1105 | |||
3523 | 1106 | for (l = list; ; l = I1NEXT(l)) { | ||
3524 | 1107 | fprintf(out, " "); | ||
3525 | 1108 | if (l == pointer) fprintf(out, ">"); | ||
3526 | 1109 | if (l == I1CUTOFF(pointer)) fprintf(out, "^"); | ||
3527 | 1110 | if (I1INSTONE(l) == NULL) { | ||
3528 | 1111 | fprintf(out, "@"); | ||
3529 | 1112 | } else { | ||
3530 | 1113 | if (I1INSTONE(l)->next != NULL) { | ||
3531 | 1114 | fprintf(out, "|"); | ||
3532 | 1115 | } | ||
3533 | 1116 | if (I1EXPANDED(l)) { | ||
3534 | 1117 | fprintf(out, "+"); | ||
3535 | 1118 | } | ||
3536 | 1119 | if (I1CUR(l) == NULL) { | ||
3537 | 1120 | fprintf(out, "*%s", I1INSTONE(l)->value->pkg->package); | ||
3538 | 1121 | } else { | ||
3539 | 1122 | fprintf(out, "%s", I1CUR(l)->value->pkg->package); | ||
3540 | 1123 | } | ||
3541 | 1124 | } | ||
3542 | 1125 | if (l == last) break; | ||
3543 | 1126 | } | ||
3544 | 1127 | fprintf(out, " ###\n"); | ||
3545 | 1128 | fflush(out); | ||
3546 | 1129 | } | ||
3547 | 1130 | |||
3548 | 1131 | int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof) { | ||
3549 | 1132 | /* We use pkg->installed, pkg->conflicted to note how many | ||
3550 | 1133 | * times we've used this pkg to satisfy a dependency or installed | ||
3551 | 1134 | * a package that conflicts with it. | ||
3552 | 1135 | * Thus: pkg->installed == 0, or pkg->conflicted == 0 | ||
3553 | 1136 | * | ||
3554 | 1137 | * We assume these are okay initially, aren't being played with | ||
3555 | 1138 | * concurrently elsewhere, and make sure they're still okay when | ||
3556 | 1139 | * we return. | ||
3557 | 1140 | */ | ||
3558 | 1141 | |||
3559 | 1142 | instonelist *list; | ||
3560 | 1143 | instonelist *last; | ||
3561 | 1144 | |||
3562 | 1145 | instonelist *pointer; | ||
3563 | 1146 | |||
3564 | 1147 | unsigned long counter = 500000000; | ||
3565 | 1148 | |||
3566 | 1149 | int last_max_inst = max_install; | ||
3567 | 1150 | int last_max_instone = max_instone_len; | ||
3568 | 1151 | int last_max_conflict = max_conflicted; | ||
3569 | 1152 | |||
3570 | 1153 | { | ||
3571 | 1154 | collpackagelist *cpkg; | ||
3572 | 1155 | for (cpkg = instoneof; cpkg; cpkg = cpkg->next) { | ||
3573 | 1156 | if (cpkg->value->installable == YES) { | ||
3574 | 1157 | free_collpackagelist(instoneof); | ||
3575 | 1158 | return 1; | ||
3576 | 1159 | } | ||
3577 | 1160 | } | ||
3578 | 1161 | } | ||
3579 | 1162 | |||
3580 | 1163 | list = insert_instonelist(NULL, instoneof); | ||
3581 | 1164 | |||
3582 | 1165 | last = list; | ||
3583 | 1166 | pointer = list; | ||
3584 | 1167 | |||
3585 | 1168 | while(--counter > 0 && pointer) { | ||
3586 | 1169 | deplistlist *dep; | ||
3587 | 1170 | dpkg_collected_package *instpkg; /* convenient alias */ | ||
3588 | 1171 | int i; | ||
3589 | 1172 | |||
3590 | 1173 | #ifndef NDEBUG | ||
3591 | 1174 | { | ||
3592 | 1175 | instonelist *p; | ||
3593 | 1176 | for (p = list; p != pointer; p = I1NEXT(p)) { | ||
3594 | 1177 | assert(p != NULL); | ||
3595 | 1178 | assert(I1CUR(p) != NULL); | ||
3596 | 1179 | assert(I1CUR(p)->value != NULL); | ||
3597 | 1180 | assert(I1CUR(p)->value->installed > 0); | ||
3598 | 1181 | assert(I1CUR(p)->value->conflicted == 0); | ||
3599 | 1182 | } | ||
3600 | 1183 | if (I1NEXT(pointer) == NULL) { | ||
3601 | 1184 | assert(pointer == last); | ||
3602 | 1185 | } else { | ||
3603 | 1186 | for (p = I1NEXT(pointer); p; p = I1NEXT(p)) { | ||
3604 | 1187 | if (I1NEXT(p) == NULL) { | ||
3605 | 1188 | assert(p == last); | ||
3606 | 1189 | } | ||
3607 | 1190 | assert(I1CUR(p) == NULL); | ||
3608 | 1191 | } | ||
3609 | 1192 | } | ||
3610 | 1193 | } | ||
3611 | 1194 | #endif | ||
3612 | 1195 | |||
3613 | 1196 | #ifdef DIAGNOSE | ||
3614 | 1197 | debug_checkinstallable(stdout, list, last, pointer); | ||
3615 | 1198 | #endif | ||
3616 | 1199 | |||
3617 | 1200 | if (I1CUR(pointer) == NULL) { | ||
3618 | 1201 | I1CUR(pointer) = I1INSTONE(pointer); | ||
3619 | 1202 | /* try to choose an already installed package if there is one */ | ||
3620 | 1203 | while (I1CUR(pointer) != NULL) { | ||
3621 | 1204 | if (I1CUR(pointer)->value->installed != 0) { | ||
3622 | 1205 | break; | ||
3623 | 1206 | } | ||
3624 | 1207 | I1CUR(pointer) = I1CUR(pointer)->next; | ||
3625 | 1208 | } | ||
3626 | 1209 | if (I1CUR(pointer) == NULL) { | ||
3627 | 1210 | I1CUR(pointer) = I1INSTONE(pointer); | ||
3628 | 1211 | } | ||
3629 | 1212 | assert(I1CUR(pointer) || !I1INSTONE(pointer)); | ||
3630 | 1213 | |||
3631 | 1214 | I1CUTOFF(pointer) = last; | ||
3632 | 1215 | } else { | ||
3633 | 1216 | uninstall(pkgs, I1CUR(pointer)->value); | ||
3634 | 1217 | trim_instonelist_after(I1CUTOFF(pointer)); | ||
3635 | 1218 | last = I1CUTOFF(pointer); | ||
3636 | 1219 | |||
3637 | 1220 | if (I1CUR(pointer)->value->installed > 0) { | ||
3638 | 1221 | /* this dependency isn't the issue -- even doing | ||
3639 | 1222 | * nothing to satisfy it (ie, using an already | ||
3640 | 1223 | * installed package) doesn't do any good. So give up. | ||
3641 | 1224 | */ | ||
3642 | 1225 | I1CUR(pointer) = NULL; | ||
3643 | 1226 | } else { | ||
3644 | 1227 | I1CUR(pointer) = I1CUR(pointer)->next; | ||
3645 | 1228 | } | ||
3646 | 1229 | } | ||
3647 | 1230 | |||
3648 | 1231 | while(I1CUR(pointer) && !caninstall(pkgs, I1CUR(pointer)->value)) { | ||
3649 | 1232 | I1CUR(pointer) = I1CUR(pointer)->next; | ||
3650 | 1233 | } | ||
3651 | 1234 | |||
3652 | 1235 | if (I1CUR(pointer) == NULL) { | ||
3653 | 1236 | if (I1PREV(pointer) == NULL) break; | ||
3654 | 1237 | pointer = I1PREV(pointer); | ||
3655 | 1238 | continue; | ||
3656 | 1239 | } | ||
3657 | 1240 | |||
3658 | 1241 | instpkg = I1CUR(pointer)->value; | ||
3659 | 1242 | |||
3660 | 1243 | install(pkgs, instpkg); | ||
3661 | 1244 | |||
3662 | 1245 | assert(instpkg->installed > 0); | ||
3663 | 1246 | if (instpkg->installed == 1) { | ||
3664 | 1247 | /* if it's been installed exactly once, then this must've been | ||
3665 | 1248 | * the first time it was touched, so we need to look at the | ||
3666 | 1249 | * dependencies. If it's the second or later, then we don't care | ||
3667 | 1250 | * about them. | ||
3668 | 1251 | */ | ||
3669 | 1252 | |||
3670 | 1253 | /* if any of the deps can't be satisfied, don't move on */ | ||
3671 | 1254 | int bother = 1; | ||
3672 | 1255 | |||
3673 | 1256 | int expanded = I1EXPANDED(pointer); | ||
3674 | 1257 | |||
3675 | 1258 | for (i = 0; i < 4; i++) { | ||
3676 | 1259 | if (!dependency_counts[i]) continue; | ||
3677 | 1260 | for (dep = instpkg->pkg->depends[i]; | ||
3678 | 1261 | dep != NULL; dep = dep->next) | ||
3679 | 1262 | { | ||
3680 | 1263 | collpackagelist *thisdep = get_matching(pkgs, dep->value, __LINE__); | ||
3681 | 1264 | |||
3682 | 1265 | if (thisdep == NULL) { | ||
3683 | 1266 | bother = 0; | ||
3684 | 1267 | |||
3685 | 1268 | } else if (thisdep != NULL && thisdep->next == NULL) { | ||
3686 | 1269 | collpackagelist *x; | ||
3687 | 1270 | |||
3688 | 1271 | /* if there's only one way of fulfilling this dep, | ||
3689 | 1272 | * do it "ASAP" | ||
3690 | 1273 | */ | ||
3691 | 1274 | |||
3692 | 1275 | /* optimisation: if thisdep == foo, but the parent | ||
3693 | 1276 | * was foo|bar, then we already know "foo" is not going | ||
3694 | 1277 | * to work in this combination, and we can skip it. | ||
3695 | 1278 | * | ||
3696 | 1279 | * This deals with cases like X deps: Y|bar, bar deps: Y | ||
3697 | 1280 | * where bar is a virtual package; cf xlibs | ||
3698 | 1281 | */ | ||
3699 | 1282 | for (x = I1INSTONE(pointer); x != I1CUR(pointer); x = x->next) { | ||
3700 | 1283 | if (x->value == thisdep->value) { | ||
3701 | 1284 | bother = 0; | ||
3702 | 1285 | break; | ||
3703 | 1286 | } | ||
3704 | 1287 | } | ||
3705 | 1288 | |||
3706 | 1289 | if (I1INSTONE(pointer)->next == NULL) { | ||
3707 | 1290 | /* the parent of this entry essentially depends | ||
3708 | 1291 | * on this too, so we'll get it out of the way | ||
3709 | 1292 | * ASAP, to reduce the degree of exponentiation | ||
3710 | 1293 | * in bad cases. | ||
3711 | 1294 | * | ||
3712 | 1295 | * _However_ we only want to do this _once_ for | ||
3713 | 1296 | * any particular node. | ||
3714 | 1297 | */ | ||
3715 | 1298 | if (expanded) { | ||
3716 | 1299 | /* thisdep isn't used! */ | ||
3717 | 1300 | free_collpackagelist(thisdep); | ||
3718 | 1301 | } else { | ||
3719 | 1302 | insert_instonelist(pointer, thisdep); | ||
3720 | 1303 | I1EXPANDED(pointer) = 1; | ||
3721 | 1304 | } | ||
3722 | 1305 | } else { | ||
3723 | 1306 | insert_instonelist(I1CUTOFF(pointer), thisdep); | ||
3724 | 1307 | } | ||
3725 | 1308 | if (I1NEXT(last)) last = I1NEXT(last); | ||
3726 | 1309 | assert(!I1NEXT(last)); | ||
3727 | 1310 | |||
3728 | 1311 | } else { | ||
3729 | 1312 | /* otherwise it's a multi possibility dep, so do it | ||
3730 | 1313 | * at the end | ||
3731 | 1314 | */ | ||
3732 | 1315 | |||
3733 | 1316 | last = insert_instonelist(last, thisdep); | ||
3734 | 1317 | } | ||
3735 | 1318 | } | ||
3736 | 1319 | } | ||
3737 | 1320 | if (!bother) { | ||
3738 | 1321 | /* stay where we are, and try the next possibility */ | ||
3739 | 1322 | continue; | ||
3740 | 1323 | } | ||
3741 | 1324 | } | ||
3742 | 1325 | |||
3743 | 1326 | pointer = I1NEXT(pointer); | ||
3744 | 1327 | } | ||
3745 | 1328 | |||
3746 | 1329 | if (max_install>last_max_inst || max_instone_len>last_max_instone || max_conflicted >last_max_conflict) { | ||
3747 | 1330 | printf("MAX: i:%d / c:%d / i1:%d %s\n", max_install,max_conflicted,max_instone_len,instoneof->value->pkg->package); | ||
3748 | 1331 | } | ||
3749 | 1332 | |||
3750 | 1333 | if (counter == 0) { | ||
3751 | 1334 | fprintf(stderr, "AIEEE: counter overflow:"); | ||
3752 | 1335 | assert(pointer != NULL); | ||
3753 | 1336 | if (I1CUR(pointer) == NULL || I1CUR(pointer)->value == NULL) { | ||
3754 | 1337 | /* we're not guaranteed that pointer will make sense here */ | ||
3755 | 1338 | pointer = I1PREV(pointer); | ||
3756 | 1339 | } | ||
3757 | 1340 | for (; pointer != NULL; pointer = I1PREV(pointer)) { | ||
3758 | 1341 | if (I1CUR(pointer) == NULL) { | ||
3759 | 1342 | /* should only happen at pointer, so not here */ | ||
3760 | 1343 | fprintf(stderr, " >> eep, no packages at pointer <<"); | ||
3761 | 1344 | continue; | ||
3762 | 1345 | } | ||
3763 | 1346 | if (I1CUR(pointer)->value == NULL) { | ||
3764 | 1347 | /* should never happen */ | ||
3765 | 1348 | fprintf(stderr, " >> eep, no package selected <<"); | ||
3766 | 1349 | continue; | ||
3767 | 1350 | } | ||
3768 | 1351 | fprintf(stderr, " %s%s", | ||
3769 | 1352 | (I1INSTONE(pointer)->next == NULL ? "" : "|"), | ||
3770 | 1353 | I1CUR(pointer)->value->pkg->package); | ||
3771 | 1354 | uninstall(pkgs, I1CUR(pointer)->value); | ||
3772 | 1355 | } | ||
3773 | 1356 | fprintf(stderr, ".\n"); | ||
3774 | 1357 | free_instonelist(list); | ||
3775 | 1358 | return 0; | ||
3776 | 1359 | } | ||
3777 | 1360 | |||
3778 | 1361 | if (pointer == NULL) { | ||
3779 | 1362 | dpkg_collected_package *cpkg = I1CUR(list)->value; | ||
3780 | 1363 | assert(cpkg->installable != YES); | ||
3781 | 1364 | cpkg->installable = YES; | ||
3782 | 1365 | for (pointer = last; pointer != NULL; pointer = I1PREV(pointer)) { | ||
3783 | 1366 | if (I1CUR(pointer)->value->installed == 1) { | ||
3784 | 1367 | packagenamelist **p = &I1CUR(pointer)->value->mayaffect; | ||
3785 | 1368 | #if 0 | ||
3786 | 1369 | while ( *p && (*p)->value < cpkg->pkg->package ) { | ||
3787 | 1370 | p = &(*p)->next; | ||
3788 | 1371 | } | ||
3789 | 1372 | if (*p == NULL || (*p)->value > cpkg->pkg->package) | ||
3790 | 1373 | #endif | ||
3791 | 1374 | { | ||
3792 | 1375 | insert_packagenamelist(p, cpkg->pkg->package); | ||
3793 | 1376 | } | ||
3794 | 1377 | } | ||
3795 | 1378 | uninstall(pkgs, I1CUR(pointer)->value); | ||
3796 | 1379 | } | ||
3797 | 1380 | free_instonelist(list); | ||
3798 | 1381 | return 1; | ||
3799 | 1382 | } else { | ||
3800 | 1383 | assert(I1CUR(list) == NULL); | ||
3801 | 1384 | free_instonelist(list); | ||
3802 | 1385 | return 0; | ||
3803 | 1386 | } | ||
3804 | 1387 | } | ||
3805 | 1388 | |||
3806 | 1389 | /******************/ | ||
3807 | 1390 | |||
3808 | 1391 | HASH_IMPL(sourcetbl, char *, dpkg_source *, SIZEOFHASHMAP, strhash, strcmp, | ||
3809 | 1392 | KEEP(char*), free_source); | ||
3810 | 1393 | |||
3811 | 1394 | static dpkg_sources *read_sources_file(char *filename, int n_arches) { | ||
3812 | 1395 | FILE *f; | ||
3813 | 1396 | dpkg_sources *result; | ||
3814 | 1397 | dpkg_source *src; | ||
3815 | 1398 | int i; | ||
3816 | 1399 | |||
3817 | 1400 | f = fopen(filename, "r"); | ||
3818 | 1401 | if (f == NULL && errno != ENOENT) { | ||
3819 | 1402 | die("read_sources_file: couldn't open file:"); | ||
3820 | 1403 | } | ||
3821 | 1404 | |||
3822 | 1405 | result = block_malloc(sizeof(dpkg_sources)); | ||
3823 | 1406 | if (result == NULL) die("read_sources_file alloc 1:"); | ||
3824 | 1407 | |||
3825 | 1408 | result->n_arches = n_arches; | ||
3826 | 1409 | result->archname = block_malloc(sizeof(char*) * n_arches); | ||
3827 | 1410 | if (result->archname == NULL) die("read_sources_file alloc 2:"); | ||
3828 | 1411 | for (i = 0; i < n_arches; i++) result->archname[i] = NULL; | ||
3829 | 1412 | result->unclaimedpackages = block_malloc(sizeof(ownedpackagelist*) | ||
3830 | 1413 | * n_arches); | ||
3831 | 1414 | if (result->unclaimedpackages == NULL) die("read_sources_file alloc 3:"); | ||
3832 | 1415 | for (i = 0; i < n_arches; i++) result->unclaimedpackages[i] = NULL; | ||
3833 | 1416 | |||
3834 | 1417 | result->sources = new_sourcetbl(); | ||
3835 | 1418 | |||
3836 | 1419 | if (f != NULL) { | ||
3837 | 1420 | while ((src = read_source(f, result))) { | ||
3838 | 1421 | dpkg_source *old = lookup_sourcetbl(result->sources, src->package); | ||
3839 | 1422 | if (old == NULL) { | ||
3840 | 1423 | add_sourcetbl(result->sources, src->package, src); | ||
3841 | 1424 | } else { | ||
3842 | 1425 | if (versioncmp(old->version, src->version) || 1) { | ||
3843 | 1426 | int i; | ||
3844 | 1427 | old = replace_sourcetbl(result->sources, src->package, src); | ||
3845 | 1428 | for (i = 0; i < old->owner->n_arches; i++) { | ||
3846 | 1429 | assert(old->packages[i] == NULL); | ||
3847 | 1430 | } | ||
3848 | 1431 | free_source(old); | ||
3849 | 1432 | } else { | ||
3850 | 1433 | int i; | ||
3851 | 1434 | for (i = 0; i < src->owner->n_arches; i++) { | ||
3852 | 1435 | assert(src->packages[i] == NULL); | ||
3853 | 1436 | } | ||
3854 | 1437 | free_source(src); | ||
3855 | 1438 | } | ||
3856 | 1439 | } | ||
3857 | 1440 | } | ||
3858 | 1441 | fclose(f); | ||
3859 | 1442 | } | ||
3860 | 1443 | |||
3861 | 1444 | return result; | ||
3862 | 1445 | } | ||
3863 | 1446 | |||
3864 | 1447 | void free_sources(dpkg_sources *s) { | ||
3865 | 1448 | int i; | ||
3866 | 1449 | if (s == NULL) return; | ||
3867 | 1450 | free_sourcetbl(s->sources); | ||
3868 | 1451 | for (i = 0; i < s->n_arches; i++) { | ||
3869 | 1452 | /* block_free(s->archname[i]); */ | ||
3870 | 1453 | free_ownedpackagelist(s->unclaimedpackages[i]); | ||
3871 | 1454 | } | ||
3872 | 1455 | block_free(s->archname, s->n_arches * sizeof(char*)); | ||
3873 | 1456 | block_free(s->unclaimedpackages, s->n_arches * sizeof(ownedpackagelist*)); | ||
3874 | 1457 | block_free(s, sizeof(dpkg_sources)); | ||
3875 | 1458 | } | ||
3876 | 1459 | |||
3877 | 1460 | static dpkg_source *new_source(dpkg_sources *owner) { | ||
3878 | 1461 | dpkg_source *result; | ||
3879 | 1462 | int i; | ||
3880 | 1463 | |||
3881 | 1464 | result = block_malloc(sizeof(dpkg_source)); | ||
3882 | 1465 | if (result == NULL) die("new_source alloc 1:"); | ||
3883 | 1466 | |||
3884 | 1467 | result->package = NULL; | ||
3885 | 1468 | result->version = NULL; | ||
3886 | 1469 | result->details = NULL; | ||
3887 | 1470 | result->fake = 0; | ||
3888 | 1471 | |||
3889 | 1472 | result->owner = owner; | ||
3890 | 1473 | result->packages = block_malloc(sizeof(packagelist*) * owner->n_arches); | ||
3891 | 1474 | if (result->packages == NULL) die("new_source alloc 2:"); | ||
3892 | 1475 | for (i = 0; i < owner->n_arches; i++) { | ||
3893 | 1476 | result->packages[i] = NULL; | ||
3894 | 1477 | } | ||
3895 | 1478 | |||
3896 | 1479 | return result; | ||
3897 | 1480 | } | ||
3898 | 1481 | |||
3899 | 1482 | static dpkg_source *read_source(FILE *f, dpkg_sources *owner) { | ||
3900 | 1483 | dpkg_source *result; | ||
3901 | 1484 | dpkg_paragraph *para; | ||
3902 | 1485 | dpkg_entry *e; | ||
3903 | 1486 | |||
3904 | 1487 | para = read_paragraph(f); | ||
3905 | 1488 | if (para == NULL) return NULL; | ||
3906 | 1489 | |||
3907 | 1490 | result = new_source(owner); | ||
3908 | 1491 | result->details = para; | ||
3909 | 1492 | |||
3910 | 1493 | for (e = ¶->entry[0]; e < ¶->entry[para->n_entries]; e++) { | ||
3911 | 1494 | if (strcmp("Package", e->name) == 0) { | ||
3912 | 1495 | result->package = my_strdup(e->value); | ||
3913 | 1496 | if (result->package == NULL) | ||
3914 | 1497 | die("read_source strdup:"); | ||
3915 | 1498 | result->package[strlen(result->package)-1] = '\0'; | ||
3916 | 1499 | } | ||
3917 | 1500 | |||
3918 | 1501 | if (strcmp("Version", e->name) == 0) { | ||
3919 | 1502 | result->version = my_strdup(e->value); | ||
3920 | 1503 | if (result->version == NULL) | ||
3921 | 1504 | die("read_source strdup:"); | ||
3922 | 1505 | result->version[strlen(result->version)-1] = '\0'; | ||
3923 | 1506 | } | ||
3924 | 1507 | } | ||
3925 | 1508 | |||
3926 | 1509 | return result; | ||
3927 | 1510 | } | ||
3928 | 1511 | |||
3929 | 1512 | void free_source(dpkg_source *s) { | ||
3930 | 1513 | int i; | ||
3931 | 1514 | if (s == NULL) return; | ||
3932 | 1515 | assert(s->owner != NULL); /* shouldn't have allocated it */ | ||
3933 | 1516 | /* block_free(s->package); */ | ||
3934 | 1517 | /* block_free(s->version); */ | ||
3935 | 1518 | free_paragraph(s->details); | ||
3936 | 1519 | for (i = 0; i < s->owner->n_arches; i++) { | ||
3937 | 1520 | free_ownedpackagelist(s->packages[i]); | ||
3938 | 1521 | } | ||
3939 | 1522 | block_free(s->packages, s->owner->n_arches * sizeof(ownedpackagelist*)); | ||
3940 | 1523 | block_free(s, sizeof(dpkg_source)); | ||
3941 | 1524 | } | ||
3942 | 1525 | |||
3943 | 1526 | /******************************/ | ||
3944 | 1527 | |||
3945 | 1528 | dpkg_sources *read_directory(char *dir, int n_arches, char *archname[]) { | ||
3946 | 1529 | char buf[1000]; | ||
3947 | 1530 | dpkg_sources *srcs; | ||
3948 | 1531 | int i; | ||
3949 | 1532 | |||
3950 | 1533 | snprintf(buf, 1000, "%s/Sources", dir); | ||
3951 | 1534 | srcs = read_sources_file(buf, n_arches); | ||
3952 | 1535 | |||
3953 | 1536 | for (i = 0; i < n_arches; i++) { | ||
3954 | 1537 | FILE *f; | ||
3955 | 1538 | dpkg_package *pkg; | ||
3956 | 1539 | |||
3957 | 1540 | srcs->archname[i] = my_strdup(archname[i]); | ||
3958 | 1541 | |||
3959 | 1542 | snprintf(buf, 1000, "%s/Packages_%s", dir, archname[i]); | ||
3960 | 1543 | f = fopen(buf, "r"); | ||
3961 | 1544 | if (f == NULL && errno != ENOENT) die("load_dirctory fopen:"); | ||
3962 | 1545 | if (f != NULL) { | ||
3963 | 1546 | while ((pkg = read_package(f))) { | ||
3964 | 1547 | dpkg_source *src = lookup_sourcetbl(srcs->sources, pkg->source); | ||
3965 | 1548 | if (src == NULL) { | ||
3966 | 1549 | src = new_source(srcs); | ||
3967 | 1550 | src->fake = 1; | ||
3968 | 1551 | src->package = my_strdup(pkg->source); | ||
3969 | 1552 | src->version = my_strdup(pkg->source_ver); | ||
3970 | 1553 | add_sourcetbl(srcs->sources, src->package, src); | ||
3971 | 1554 | } | ||
3972 | 1555 | insert_ownedpackagelist(&src->packages[i], pkg); | ||
3973 | 1556 | } | ||
3974 | 1557 | fclose(f); | ||
3975 | 1558 | } | ||
3976 | 1559 | } | ||
3977 | 1560 | |||
3978 | 1561 | return srcs; | ||
3979 | 1562 | } | ||
3980 | 1563 | |||
3981 | 1564 | void write_directory(char *dir, dpkg_sources *srcs) { | ||
3982 | 1565 | FILE *src; | ||
3983 | 1566 | FILE *archfile[100]; | ||
3984 | 1567 | char buf[1000]; | ||
3985 | 1568 | int i; | ||
3986 | 1569 | sourcetbl_iter srciter; | ||
3987 | 1570 | |||
3988 | 1571 | snprintf(buf, 1000, "%s/Sources", dir); | ||
3989 | 1572 | src = fopen(buf, "w"); | ||
3990 | 1573 | if (!src) die("write_directory: Couldn't open Sources file for output"); | ||
3991 | 1574 | |||
3992 | 1575 | for (i = 0; i < srcs->n_arches; i++) { | ||
3993 | 1576 | snprintf(buf, 1000, "%s/Packages_%s", dir, srcs->archname[i]); | ||
3994 | 1577 | archfile[i] = fopen(buf, "w"); | ||
3995 | 1578 | } | ||
3996 | 1579 | |||
3997 | 1580 | for (srciter = first_sourcetbl(srcs->sources); | ||
3998 | 1581 | !done_sourcetbl(srciter); | ||
3999 | 1582 | srciter = next_sourcetbl(srciter)) | ||
4000 | 1583 | { | ||
4001 | 1584 | ownedpackagelist *p; | ||
4002 | 1585 | int i; | ||
4003 | 1586 | |||
4004 | 1587 | if (!srciter.v->fake) | ||
4005 | 1588 | write_paragraph(src, srciter.v->details); | ||
4006 | 1589 | |||
4007 | 1590 | for (i = 0; i < srcs->n_arches; i++) { | ||
4008 | 1591 | for (p = srciter.v->packages[i]; p != NULL; p = p->next) { | ||
4009 | 1592 | write_paragraph(archfile[i], p->value->details); | ||
4010 | 1593 | } | ||
4011 | 1594 | } | ||
4012 | 1595 | } | ||
4013 | 1596 | |||
4014 | 1597 | fclose(src); | ||
4015 | 1598 | for (i = 0; i < srcs->n_arches; i++) { | ||
4016 | 1599 | fclose(archfile[i]); | ||
4017 | 1600 | } | ||
4018 | 1601 | } | ||
4019 | 1602 | |||
4020 | 1603 | /*********************/ | ||
4021 | 1604 | |||
4022 | 1605 | HASH_IMPL(sourcenotetbl, char *, dpkg_source_note *, SIZEOFHASHMAP, strhash, strcmp, | ||
4023 | 1606 | KEEP(char*), free_source_note); | ||
4024 | 1607 | |||
4025 | 1608 | dpkg_source_note *new_source_note(dpkg_source *src, int n_arches) { | ||
4026 | 1609 | dpkg_source_note *result = block_malloc(sizeof(dpkg_source_note)); | ||
4027 | 1610 | int i; | ||
4028 | 1611 | |||
4029 | 1612 | if (result == NULL) die("new_source_note alloc 1:"); | ||
4030 | 1613 | result->source = src; | ||
4031 | 1614 | result->n_arches = n_arches; | ||
4032 | 1615 | result->binaries = block_malloc(n_arches * sizeof(packagelist*)); | ||
4033 | 1616 | if (result->binaries == NULL) die("new_source_note alloc 2:"); | ||
4034 | 1617 | for (i = 0; i < n_arches; i++) { | ||
4035 | 1618 | result->binaries[i] = NULL; | ||
4036 | 1619 | } | ||
4037 | 1620 | return result; | ||
4038 | 1621 | } | ||
4039 | 1622 | |||
4040 | 1623 | void free_source_note(dpkg_source_note *srcn) { | ||
4041 | 1624 | int i; | ||
4042 | 1625 | |||
4043 | 1626 | if (srcn == NULL) return; | ||
4044 | 1627 | |||
4045 | 1628 | if (srcn->binaries != NULL) { | ||
4046 | 1629 | for (i = 0; i < srcn->n_arches; i++) { | ||
4047 | 1630 | free_packagelist(srcn->binaries[i]); | ||
4048 | 1631 | } | ||
4049 | 1632 | block_free(srcn->binaries, sizeof(packagelist*) * srcn->n_arches); | ||
4050 | 1633 | } | ||
4051 | 1634 | block_free(srcn, sizeof(dpkg_source_note)); | ||
4052 | 1635 | } | ||
4053 | 1636 | |||
4054 | 1637 | #ifdef DEBUG | ||
4055 | 1638 | static int is_sources_note(dpkg_sources_note *srcsn) { | ||
4056 | 1639 | int i; | ||
4057 | 1640 | |||
4058 | 1641 | assert(srcsn != NULL); | ||
4059 | 1642 | assert(srcsn->magic == 0xa1eebabe); | ||
4060 | 1643 | assert(srcsn->pkgs != NULL); | ||
4061 | 1644 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4062 | 1645 | assert(srcsn->pkgs[i] != NULL && srcsn->archname[i] != NULL); | ||
4063 | 1646 | assert(strcmp(srcsn->archname[i], srcsn->pkgs[i]->arch) == 0); | ||
4064 | 1647 | } | ||
4065 | 1648 | |||
4066 | 1649 | return 1; | ||
4067 | 1650 | } | ||
4068 | 1651 | #endif | ||
4069 | 1652 | |||
4070 | 1653 | dpkg_sources_note *new_sources_note(int n_arches, char **archname) { | ||
4071 | 1654 | dpkg_sources_note *result = block_malloc(sizeof(dpkg_sources_note)); | ||
4072 | 1655 | int i; | ||
4073 | 1656 | |||
4074 | 1657 | if (result == NULL) die("new_sources_note alloc 1:"); | ||
4075 | 1658 | result->magic = 0xA1EEBABE; | ||
4076 | 1659 | result->sources = new_sourcenotetbl(); | ||
4077 | 1660 | result->pkgs = block_malloc(n_arches * sizeof(dpkg_packages*)); | ||
4078 | 1661 | if (result->pkgs == NULL) die("new_sources_note alloc 2:"); | ||
4079 | 1662 | result->archname = block_malloc(n_arches * sizeof(char*)); | ||
4080 | 1663 | if (result->archname == NULL) die("new_sources_note alloc 3:"); | ||
4081 | 1664 | |||
4082 | 1665 | result->n_arches = n_arches; | ||
4083 | 1666 | for (i = 0; i < n_arches; i++) { | ||
4084 | 1667 | result->archname[i] = my_strdup(archname[i]); | ||
4085 | 1668 | result->pkgs[i] = new_packages(result->archname[i]); | ||
4086 | 1669 | } | ||
4087 | 1670 | result->undo = NULL; | ||
4088 | 1671 | return result; | ||
4089 | 1672 | } | ||
4090 | 1673 | |||
4091 | 1674 | void free_sources_note(dpkg_sources_note *srcsn) { | ||
4092 | 1675 | int i; | ||
4093 | 1676 | if (srcsn == NULL) return; | ||
4094 | 1677 | assert(is_sources_note(srcsn)); | ||
4095 | 1678 | srcsn->magic = 0xBABEA1EE; | ||
4096 | 1679 | free_sourcenotetbl(srcsn->sources); | ||
4097 | 1680 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4098 | 1681 | free_packages(srcsn->pkgs[i]); | ||
4099 | 1682 | /* block_free(srcsn->archname[i]); */ | ||
4100 | 1683 | } | ||
4101 | 1684 | block_free(srcsn->pkgs, sizeof(dpkg_packages*) * srcsn->n_arches); | ||
4102 | 1685 | block_free(srcsn->archname, sizeof(char*) * srcsn->n_arches); | ||
4103 | 1686 | free_source_note_listlist(srcsn->undo); | ||
4104 | 1687 | block_free(srcsn, sizeof(dpkg_sources_note)); | ||
4105 | 1688 | } | ||
4106 | 1689 | |||
4107 | 1690 | static void new_op(dpkg_sources_note *srcsn) { | ||
4108 | 1691 | assert(is_sources_note(srcsn)); | ||
4109 | 1692 | insert_source_note_listlist(&srcsn->undo, NULL); | ||
4110 | 1693 | } | ||
4111 | 1694 | static void save_source_note(dpkg_sources_note *srcsn, dpkg_source_note *srcn) { | ||
4112 | 1695 | source_note_list **where; | ||
4113 | 1696 | assert(is_sources_note(srcsn)); | ||
4114 | 1697 | assert(srcsn->undo != NULL); | ||
4115 | 1698 | |||
4116 | 1699 | for (where = &srcsn->undo->value; | ||
4117 | 1700 | *where != NULL; | ||
4118 | 1701 | where = &(*where)->next) | ||
4119 | 1702 | { | ||
4120 | 1703 | if ((*where)->value->source == srcn->source) | ||
4121 | 1704 | return; /* already saved */ | ||
4122 | 1705 | } | ||
4123 | 1706 | |||
4124 | 1707 | insert_source_note_list(where, copy_source_note(srcn)); | ||
4125 | 1708 | } | ||
4126 | 1709 | static void save_empty_source_note(dpkg_sources_note *srcsn, dpkg_source *src) { | ||
4127 | 1710 | dpkg_source_note *srcn; | ||
4128 | 1711 | source_note_list **where; | ||
4129 | 1712 | |||
4130 | 1713 | for (where = &srcsn->undo->value; | ||
4131 | 1714 | *where != NULL; | ||
4132 | 1715 | where = &(*where)->next) | ||
4133 | 1716 | { | ||
4134 | 1717 | if ((*where)->value->source == src) | ||
4135 | 1718 | return; /* already saved */ | ||
4136 | 1719 | } | ||
4137 | 1720 | |||
4138 | 1721 | srcn = block_malloc(sizeof(dpkg_source_note)); | ||
4139 | 1722 | if (srcn == NULL) die("save_empty_source_note alloc:"); | ||
4140 | 1723 | assert(is_sources_note(srcsn)); | ||
4141 | 1724 | |||
4142 | 1725 | srcn->source = src; | ||
4143 | 1726 | srcn->n_arches = 0; | ||
4144 | 1727 | srcn->binaries = NULL; | ||
4145 | 1728 | |||
4146 | 1729 | insert_source_note_list(where, srcn); | ||
4147 | 1730 | } | ||
4148 | 1731 | |||
4149 | 1732 | typedef enum { DO_ARCHALL = 0, SKIP_ARCHALL = 1 } do_this; | ||
4150 | 1733 | static void remove_binaries_by_arch(dpkg_sources_note *srcsn, | ||
4151 | 1734 | dpkg_source_note *srcn, int archnum, | ||
4152 | 1735 | do_this arch_all) | ||
4153 | 1736 | { | ||
4154 | 1737 | packagelist *p; | ||
4155 | 1738 | packagelist *leftovers = NULL, **addto = &leftovers; | ||
4156 | 1739 | assert(is_sources_note(srcsn)); | ||
4157 | 1740 | |||
4158 | 1741 | assert(arch_all == SKIP_ARCHALL || NULL == lookup_sourcenotetbl(srcsn->sources,srcn->source->package)); | ||
4159 | 1742 | /* if we're removing the entire binary, we should already have | ||
4160 | 1743 | * removed the source. if we're removing just the binaries on this | ||
4161 | 1744 | * arch (not arch:all) then we may be keeping the source | ||
4162 | 1745 | * | ||
4163 | 1746 | * really a logical XOR, I think. we don't rely on this assertion | ||
4164 | 1747 | * here | ||
4165 | 1748 | */ | ||
4166 | 1749 | |||
4167 | 1750 | for (p = srcn->binaries[archnum]; p != NULL; p = p->next) { | ||
4168 | 1751 | dpkg_collected_package *cpkg; | ||
4169 | 1752 | if (arch_all == SKIP_ARCHALL && p->value->arch_all) { | ||
4170 | 1753 | insert_packagelist(addto, p->value); | ||
4171 | 1754 | addto = &(*addto)->next; | ||
4172 | 1755 | continue; | ||
4173 | 1756 | } | ||
4174 | 1757 | cpkg = lookup_packagetbl(srcsn->pkgs[archnum]->packages, | ||
4175 | 1758 | p->value->package); | ||
4176 | 1759 | remove_package(srcsn->pkgs[archnum], cpkg); | ||
4177 | 1760 | } | ||
4178 | 1761 | free_packagelist(srcn->binaries[archnum]); | ||
4179 | 1762 | srcn->binaries[archnum] = leftovers; | ||
4180 | 1763 | } | ||
4181 | 1764 | |||
4182 | 1765 | typedef enum { NOTUNDOABLE = 0, UNDOABLE = 1 } undoable; | ||
4183 | 1766 | static void add_binaries_by_arch(dpkg_sources_note *srcsn, | ||
4184 | 1767 | dpkg_source_note *srcn, dpkg_source *src, | ||
4185 | 1768 | int archnum, undoable undoop, do_this arch_all) | ||
4186 | 1769 | { | ||
4187 | 1770 | ownedpackagelist *p; | ||
4188 | 1771 | const char *archname = srcsn->archname[archnum]; | ||
4189 | 1772 | int origarchnum = -1; | ||
4190 | 1773 | int i; | ||
4191 | 1774 | |||
4192 | 1775 | assert(is_sources_note(srcsn)); | ||
4193 | 1776 | assert(srcn == lookup_sourcenotetbl(srcsn->sources,srcn->source->package)); | ||
4194 | 1777 | for (i = 0; i < src->owner->n_arches; i++) { | ||
4195 | 1778 | if (strcmp(archname, src->owner->archname[i]) == 0) { | ||
4196 | 1779 | origarchnum = i; | ||
4197 | 1780 | break; | ||
4198 | 1781 | } | ||
4199 | 1782 | } | ||
4200 | 1783 | if (origarchnum == -1) return; /* nothing to add, no biggie */ | ||
4201 | 1784 | |||
4202 | 1785 | for (p = src->packages[origarchnum]; p != NULL; p = p->next) { | ||
4203 | 1786 | dpkg_collected_package *cpkg; | ||
4204 | 1787 | |||
4205 | 1788 | if (arch_all == SKIP_ARCHALL && p->value->arch_all) continue; | ||
4206 | 1789 | |||
4207 | 1790 | if ((cpkg = lookup_packagetbl(srcsn->pkgs[archnum]->packages, | ||
4208 | 1791 | p->value->package))) | ||
4209 | 1792 | { | ||
4210 | 1793 | dpkg_source_note *srcnB; | ||
4211 | 1794 | packagelist **p; | ||
4212 | 1795 | |||
4213 | 1796 | if (!undoop) { | ||
4214 | 1797 | printf("conflict w/o undo: binary %s, owned by %s, replaced by %s\n", cpkg->pkg->package, cpkg->pkg->source, src->package); | ||
4215 | 1798 | fflush(stdout); | ||
4216 | 1799 | } | ||
4217 | 1800 | srcnB = lookup_sourcenotetbl(srcsn->sources, cpkg->pkg->source); | ||
4218 | 1801 | assert(srcnB != NULL); | ||
4219 | 1802 | |||
4220 | 1803 | for (p = &srcnB->binaries[archnum]; *p != NULL; p = &(*p)->next) { | ||
4221 | 1804 | if ((*p)->value == cpkg->pkg) break; | ||
4222 | 1805 | } | ||
4223 | 1806 | assert(*p != NULL); /* binary should be from source */ | ||
4224 | 1807 | |||
4225 | 1808 | assert(undoop); | ||
4226 | 1809 | save_source_note(srcsn, srcnB); | ||
4227 | 1810 | remove_package(srcsn->pkgs[archnum], cpkg); | ||
4228 | 1811 | remove_packagelist(p); | ||
4229 | 1812 | } | ||
4230 | 1813 | |||
4231 | 1814 | add_package(srcsn->pkgs[archnum], p->value); | ||
4232 | 1815 | insert_packagelist(&srcn->binaries[archnum], p->value); | ||
4233 | 1816 | } | ||
4234 | 1817 | } | ||
4235 | 1818 | |||
4236 | 1819 | void upgrade_source(dpkg_sources_note *srcsn, dpkg_source *src) { | ||
4237 | 1820 | dpkg_source_note *srcn; | ||
4238 | 1821 | int i; | ||
4239 | 1822 | |||
4240 | 1823 | new_op(srcsn); | ||
4241 | 1824 | |||
4242 | 1825 | assert(is_sources_note(srcsn)); | ||
4243 | 1826 | /* first, find the old source, if it exists */ | ||
4244 | 1827 | srcn = remove_sourcenotetbl(srcsn->sources, src->package); | ||
4245 | 1828 | if (srcn != NULL) { | ||
4246 | 1829 | save_source_note(srcsn, srcn); | ||
4247 | 1830 | for (i = 0; i < srcn->n_arches; i++) { | ||
4248 | 1831 | remove_binaries_by_arch(srcsn, srcn, i, DO_ARCHALL); | ||
4249 | 1832 | } | ||
4250 | 1833 | free_source_note(srcn); | ||
4251 | 1834 | } else { | ||
4252 | 1835 | save_empty_source_note(srcsn, src); | ||
4253 | 1836 | } | ||
4254 | 1837 | |||
4255 | 1838 | /* then add the new one */ | ||
4256 | 1839 | srcn = new_source_note(src, srcsn->n_arches); | ||
4257 | 1840 | add_sourcenotetbl(srcsn->sources, src->package, srcn); | ||
4258 | 1841 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4259 | 1842 | add_binaries_by_arch(srcsn, srcn, src, i, UNDOABLE, DO_ARCHALL); | ||
4260 | 1843 | } | ||
4261 | 1844 | assert(is_sources_note(srcsn)); | ||
4262 | 1845 | } | ||
4263 | 1846 | |||
4264 | 1847 | void upgrade_arch(dpkg_sources_note *srcsn, dpkg_source *src, char *arch) { | ||
4265 | 1848 | dpkg_source_note *srcn; | ||
4266 | 1849 | int archnum = -1; | ||
4267 | 1850 | int i; | ||
4268 | 1851 | |||
4269 | 1852 | assert(is_sources_note(srcsn)); | ||
4270 | 1853 | /* first, find the old source */ | ||
4271 | 1854 | srcn = lookup_sourcenotetbl(srcsn->sources, src->package); | ||
4272 | 1855 | |||
4273 | 1856 | assert(srcn != NULL); | ||
4274 | 1857 | new_op(srcsn); | ||
4275 | 1858 | save_source_note(srcsn, srcn); | ||
4276 | 1859 | |||
4277 | 1860 | /* then lookup the archnum */ | ||
4278 | 1861 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4279 | 1862 | if (strcmp(arch, srcsn->archname[i]) == 0) { | ||
4280 | 1863 | archnum = i; | ||
4281 | 1864 | break; | ||
4282 | 1865 | } | ||
4283 | 1866 | } | ||
4284 | 1867 | if (archnum == -1) die("upgrade_arch: unknown arch"); | ||
4285 | 1868 | |||
4286 | 1869 | /* then remove the old stuff and add the new */ | ||
4287 | 1870 | remove_binaries_by_arch(srcsn, srcn, archnum, SKIP_ARCHALL); | ||
4288 | 1871 | add_binaries_by_arch(srcsn, srcn, src, archnum, UNDOABLE, SKIP_ARCHALL); | ||
4289 | 1872 | assert(is_sources_note(srcsn)); | ||
4290 | 1873 | } | ||
4291 | 1874 | |||
4292 | 1875 | void remove_source(dpkg_sources_note *srcsn, char *name) { | ||
4293 | 1876 | dpkg_source_note *srcn; | ||
4294 | 1877 | int i; | ||
4295 | 1878 | |||
4296 | 1879 | assert(is_sources_note(srcsn)); | ||
4297 | 1880 | srcn = remove_sourcenotetbl(srcsn->sources, name); | ||
4298 | 1881 | assert(srcn != NULL); | ||
4299 | 1882 | |||
4300 | 1883 | new_op(srcsn); | ||
4301 | 1884 | save_source_note(srcsn, srcn); | ||
4302 | 1885 | for (i = 0; i < srcn->n_arches; i++) { | ||
4303 | 1886 | remove_binaries_by_arch(srcsn, srcn, i, DO_ARCHALL); | ||
4304 | 1887 | } | ||
4305 | 1888 | free_source_note(srcn); | ||
4306 | 1889 | assert(is_sources_note(srcsn)); | ||
4307 | 1890 | } | ||
4308 | 1891 | |||
4309 | 1892 | int can_undo(dpkg_sources_note *srcsn) { | ||
4310 | 1893 | assert(is_sources_note(srcsn)); | ||
4311 | 1894 | return srcsn->undo != NULL; | ||
4312 | 1895 | } | ||
4313 | 1896 | |||
4314 | 1897 | void undo_change(dpkg_sources_note *srcsn) { | ||
4315 | 1898 | dpkg_source_note *srcnO, *srcnC; /* old, current */ | ||
4316 | 1899 | source_note_list *srcnl; | ||
4317 | 1900 | int i; | ||
4318 | 1901 | |||
4319 | 1902 | assert(is_sources_note(srcsn)); | ||
4320 | 1903 | assert(can_undo(srcsn)); | ||
4321 | 1904 | |||
4322 | 1905 | srcnl = remove_source_note_listlist(&srcsn->undo); | ||
4323 | 1906 | |||
4324 | 1907 | while(srcnl) { | ||
4325 | 1908 | srcnO = remove_source_note_list(&srcnl); | ||
4326 | 1909 | assert(srcnO != NULL); /* can_undo() implies this is true... */ | ||
4327 | 1910 | |||
4328 | 1911 | srcnC = remove_sourcenotetbl(srcsn->sources, srcnO->source->package); | ||
4329 | 1912 | if (srcnC != NULL) { | ||
4330 | 1913 | for (i = 0; i < srcnC->n_arches; i++) { | ||
4331 | 1914 | remove_binaries_by_arch(srcsn, srcnC, i, DO_ARCHALL); | ||
4332 | 1915 | } | ||
4333 | 1916 | free_source_note(srcnC); | ||
4334 | 1917 | assert(!lookup_sourcenotetbl(srcsn->sources, | ||
4335 | 1918 | srcnO->source->package)); | ||
4336 | 1919 | } | ||
4337 | 1920 | |||
4338 | 1921 | if (srcnO->binaries == NULL) { | ||
4339 | 1922 | /* no original source */ | ||
4340 | 1923 | assert(srcnC != NULL); /* some sort of no-op? freaky. */ | ||
4341 | 1924 | free_source_note(srcnO); | ||
4342 | 1925 | } else { | ||
4343 | 1926 | packagelist *p; | ||
4344 | 1927 | /* original source */ | ||
4345 | 1928 | add_sourcenotetbl(srcsn->sources, srcnO->source->package, srcnO); | ||
4346 | 1929 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4347 | 1930 | for (p = srcnO->binaries[i]; p != NULL; p = p->next) { | ||
4348 | 1931 | add_package(srcsn->pkgs[i], p->value); | ||
4349 | 1932 | } | ||
4350 | 1933 | } | ||
4351 | 1934 | } | ||
4352 | 1935 | } | ||
4353 | 1936 | } | ||
4354 | 1937 | |||
4355 | 1938 | LIST_IMPL(source_note_list, dpkg_source_note *, free_source_note, | ||
4356 | 1939 | block_malloc, block_free); | ||
4357 | 1940 | LIST_IMPL(source_note_listlist, source_note_list *, free_source_note_list, | ||
4358 | 1941 | block_malloc, block_free); | ||
4359 | 1942 | |||
4360 | 1943 | void commit_changes(dpkg_sources_note *srcsn) { | ||
4361 | 1944 | assert(is_sources_note(srcsn)); | ||
4362 | 1945 | free_source_note_listlist(srcsn->undo); | ||
4363 | 1946 | srcsn->undo = NULL; | ||
4364 | 1947 | } | ||
4365 | 1948 | |||
4366 | 1949 | dpkg_source_note *copy_source_note(dpkg_source_note *srcn) { | ||
4367 | 1950 | dpkg_source_note *srcn2; | ||
4368 | 1951 | packagelist *src, **dest; | ||
4369 | 1952 | int i; | ||
4370 | 1953 | |||
4371 | 1954 | assert(srcn->binaries != NULL); | ||
4372 | 1955 | |||
4373 | 1956 | srcn2 = block_malloc(sizeof(dpkg_source_note)); | ||
4374 | 1957 | if (srcn2 == NULL) die("copy_source_note alloc:"); | ||
4375 | 1958 | |||
4376 | 1959 | srcn2->source = srcn->source; | ||
4377 | 1960 | srcn2->n_arches = srcn->n_arches; | ||
4378 | 1961 | srcn2->binaries = block_malloc(sizeof(packagenamelist*) * srcn2->n_arches); | ||
4379 | 1962 | if (srcn2->binaries == NULL) die("copy_source_note alloc:"); | ||
4380 | 1963 | |||
4381 | 1964 | for (i = 0; i < srcn2->n_arches; i++) { | ||
4382 | 1965 | dest = &(srcn2->binaries[i]); | ||
4383 | 1966 | *dest = NULL; | ||
4384 | 1967 | for (src = srcn->binaries[i]; src; src = src->next) { | ||
4385 | 1968 | insert_packagelist(dest, src->value); | ||
4386 | 1969 | dest = &((*dest)->next); | ||
4387 | 1970 | } | ||
4388 | 1971 | } | ||
4389 | 1972 | |||
4390 | 1973 | return srcn2; | ||
4391 | 1974 | } | ||
4392 | 1975 | |||
4393 | 1976 | void write_notes(char *dir, dpkg_sources_note *srcsn) { | ||
4394 | 1977 | FILE *src; | ||
4395 | 1978 | FILE *archfile[100]; | ||
4396 | 1979 | char buf[1000]; | ||
4397 | 1980 | int i; | ||
4398 | 1981 | sourcenotetbl_iter srciter; | ||
4399 | 1982 | |||
4400 | 1983 | assert(is_sources_note(srcsn)); | ||
4401 | 1984 | snprintf(buf, 1000, "%s/Sources", dir); | ||
4402 | 1985 | src = fopen(buf, "w"); | ||
4403 | 1986 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4404 | 1987 | snprintf(buf, 1000, "%s/Packages_%s", dir, srcsn->archname[i]); | ||
4405 | 1988 | archfile[i] = fopen(buf, "w"); | ||
4406 | 1989 | } | ||
4407 | 1990 | |||
4408 | 1991 | for (srciter = first_sourcenotetbl(srcsn->sources); | ||
4409 | 1992 | !done_sourcenotetbl(srciter); | ||
4410 | 1993 | srciter = next_sourcenotetbl(srciter)) | ||
4411 | 1994 | { | ||
4412 | 1995 | packagelist *p; | ||
4413 | 1996 | int i; | ||
4414 | 1997 | |||
4415 | 1998 | if (!srciter.v->source->fake) | ||
4416 | 1999 | write_paragraph(src, srciter.v->source->details); | ||
4417 | 2000 | |||
4418 | 2001 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4419 | 2002 | for (p = srciter.v->binaries[i]; p != NULL; p = p->next) { | ||
4420 | 2003 | write_paragraph(archfile[i], p->value->details); | ||
4421 | 2004 | } | ||
4422 | 2005 | } | ||
4423 | 2006 | } | ||
4424 | 2007 | |||
4425 | 2008 | fclose(src); | ||
4426 | 2009 | for (i = 0; i < srcsn->n_arches; i++) { | ||
4427 | 2010 | fclose(archfile[i]); | ||
4428 | 2011 | } | ||
4429 | 2012 | } | ||
4430 | 2013 | |||
4431 | 0 | 2014 | ||
4432 | === added file 'update_out/dpkg.h' | |||
4433 | --- update_out/dpkg.h 1970-01-01 00:00:00 +0000 | |||
4434 | +++ update_out/dpkg.h 2015-06-09 16:34:27 +0000 | |||
4435 | @@ -0,0 +1,207 @@ | |||
4436 | 1 | #ifndef DPKG_H | ||
4437 | 2 | #define DPKG_H | ||
4438 | 3 | |||
4439 | 4 | #include "templates.h" | ||
4440 | 5 | #include "memory.h" | ||
4441 | 6 | |||
4442 | 7 | #include <stdio.h> | ||
4443 | 8 | |||
4444 | 9 | /************************************************************************** | ||
4445 | 10 | * Coping with an rfc822-esque field | ||
4446 | 11 | */ | ||
4447 | 12 | |||
4448 | 13 | typedef struct dpkg_entry dpkg_entry; | ||
4449 | 14 | struct dpkg_entry { | ||
4450 | 15 | char *name; | ||
4451 | 16 | char *value; | ||
4452 | 17 | }; | ||
4453 | 18 | |||
4454 | 19 | typedef struct dpkg_paragraph dpkg_paragraph; | ||
4455 | 20 | struct dpkg_paragraph { | ||
4456 | 21 | int n_entries; | ||
4457 | 22 | int n_allocated; | ||
4458 | 23 | dpkg_entry *entry; | ||
4459 | 24 | }; | ||
4460 | 25 | |||
4461 | 26 | /************************************************************************** | ||
4462 | 27 | * Coping with a package (or many pkgs) as an abstract entity | ||
4463 | 28 | */ | ||
4464 | 29 | |||
4465 | 30 | typedef enum {dr_NOOP,dr_LT,dr_LTEQ,dr_EQ,dr_GTEQ,dr_GT} dependency_relation; | ||
4466 | 31 | extern char *dependency_relation_sym[]; | ||
4467 | 32 | |||
4468 | 33 | typedef struct dependency dependency; | ||
4469 | 34 | struct dependency { | ||
4470 | 35 | char *package; | ||
4471 | 36 | dependency_relation op; | ||
4472 | 37 | char *version; | ||
4473 | 38 | }; | ||
4474 | 39 | |||
4475 | 40 | LIST(deplist, dependency*); | ||
4476 | 41 | LIST(deplistlist, deplist*); | ||
4477 | 42 | |||
4478 | 43 | LIST(packagenamelist, char*); | ||
4479 | 44 | LIST(ownedpackagenamelist, char*); | ||
4480 | 45 | |||
4481 | 46 | typedef struct dpkg_package dpkg_package; | ||
4482 | 47 | |||
4483 | 48 | struct dpkg_package { | ||
4484 | 49 | char *package; | ||
4485 | 50 | char *version; | ||
4486 | 51 | |||
4487 | 52 | char *source; | ||
4488 | 53 | char *source_ver; | ||
4489 | 54 | |||
4490 | 55 | int priority; | ||
4491 | 56 | |||
4492 | 57 | int arch_all; | ||
4493 | 58 | |||
4494 | 59 | deplistlist *depends[4]; | ||
4495 | 60 | deplist *conflicts; | ||
4496 | 61 | ownedpackagenamelist *provides; | ||
4497 | 62 | |||
4498 | 63 | dpkg_paragraph *details; | ||
4499 | 64 | }; | ||
4500 | 65 | |||
4501 | 66 | LIST(packagelist, dpkg_package *); | ||
4502 | 67 | LIST(ownedpackagelist, dpkg_package *); | ||
4503 | 68 | |||
4504 | 69 | typedef struct satisfieddep satisfieddep; | ||
4505 | 70 | |||
4506 | 71 | struct satisfieddep { | ||
4507 | 72 | /* dependency *dep; */ | ||
4508 | 73 | deplist *depl; | ||
4509 | 74 | packagelist *pkgs; | ||
4510 | 75 | }; | ||
4511 | 76 | |||
4512 | 77 | LIST(satisfieddeplist, satisfieddep *); | ||
4513 | 78 | |||
4514 | 79 | /************************************************************************** | ||
4515 | 80 | * Coping with a source package (and collections thereof) as an abstract | ||
4516 | 81 | * entity, owning a bunch of binary packages | ||
4517 | 82 | */ | ||
4518 | 83 | |||
4519 | 84 | typedef struct dpkg_source dpkg_source; | ||
4520 | 85 | struct dpkg_source { | ||
4521 | 86 | char *package; | ||
4522 | 87 | char *version; | ||
4523 | 88 | |||
4524 | 89 | int fake; | ||
4525 | 90 | |||
4526 | 91 | struct dpkg_sources *owner; | ||
4527 | 92 | ownedpackagelist **packages; /* one for each architecture */ | ||
4528 | 93 | |||
4529 | 94 | dpkg_paragraph *details; | ||
4530 | 95 | }; | ||
4531 | 96 | |||
4532 | 97 | HASH(sourcetbl,char *,dpkg_source *); | ||
4533 | 98 | |||
4534 | 99 | typedef struct dpkg_sources dpkg_sources; | ||
4535 | 100 | struct dpkg_sources { | ||
4536 | 101 | int n_arches; | ||
4537 | 102 | char **archname; | ||
4538 | 103 | sourcetbl *sources; | ||
4539 | 104 | ownedpackagelist **unclaimedpackages; /* one for each arch */ | ||
4540 | 105 | }; | ||
4541 | 106 | |||
4542 | 107 | /************************************************************************** | ||
4543 | 108 | */ | ||
4544 | 109 | |||
4545 | 110 | typedef struct dpkg_collected_package dpkg_collected_package; | ||
4546 | 111 | struct dpkg_collected_package { | ||
4547 | 112 | dpkg_package *pkg; | ||
4548 | 113 | |||
4549 | 114 | int installed, conflicted; | ||
4550 | 115 | |||
4551 | 116 | enum { UNKNOWN, YES } installable; | ||
4552 | 117 | packagenamelist *mayaffect; | ||
4553 | 118 | |||
4554 | 119 | /* on update, the installability_checked of each /mayaffect/ed package | ||
4555 | 120 | * is cleared, and the mayaffect list is cleared. | ||
4556 | 121 | * | ||
4557 | 122 | * note that installable = NO couldn't be maintained over adding a package | ||
4558 | 123 | * to testing. installable = YES can be, thanks to the mayaffect list | ||
4559 | 124 | * (once a package is removed, everything it mayaffect must be set back | ||
4560 | 125 | * to unknown, but everything else is okay) | ||
4561 | 126 | */ | ||
4562 | 127 | }; | ||
4563 | 128 | |||
4564 | 129 | LIST(collpackagelist, dpkg_collected_package *); | ||
4565 | 130 | |||
4566 | 131 | /************************************************************************** | ||
4567 | 132 | */ | ||
4568 | 133 | |||
4569 | 134 | typedef struct dpkg_provision dpkg_provision; | ||
4570 | 135 | struct dpkg_provision { | ||
4571 | 136 | char *version; | ||
4572 | 137 | dpkg_collected_package *pkg; | ||
4573 | 138 | }; | ||
4574 | 139 | |||
4575 | 140 | LIST(virtualpkg, dpkg_provision); | ||
4576 | 141 | |||
4577 | 142 | HASH(virtualpkgtbl,char *,virtualpkg *); | ||
4578 | 143 | HASH(packagetbl,char *,dpkg_collected_package *); | ||
4579 | 144 | |||
4580 | 145 | typedef struct dpkg_packages dpkg_packages; | ||
4581 | 146 | struct dpkg_packages { | ||
4582 | 147 | char *arch; | ||
4583 | 148 | packagetbl *packages; | ||
4584 | 149 | virtualpkgtbl *virtualpkgs; | ||
4585 | 150 | }; | ||
4586 | 151 | |||
4587 | 152 | typedef struct dpkg_source_note dpkg_source_note; | ||
4588 | 153 | struct dpkg_source_note { | ||
4589 | 154 | dpkg_source *source; /* unowned */ | ||
4590 | 155 | int n_arches; | ||
4591 | 156 | packagelist **binaries; /* one for each arch */ | ||
4592 | 157 | }; | ||
4593 | 158 | HASH(sourcenotetbl, char *, dpkg_source_note *); | ||
4594 | 159 | |||
4595 | 160 | LIST(source_note_list, dpkg_source_note *); | ||
4596 | 161 | /* contains a copy of the previous source_note */ | ||
4597 | 162 | LIST(source_note_listlist, source_note_list *); | ||
4598 | 163 | /* contains a copy of all the source_notes modified by the last op */ | ||
4599 | 164 | |||
4600 | 165 | typedef struct dpkg_sources_note dpkg_sources_note; | ||
4601 | 166 | struct dpkg_sources_note { | ||
4602 | 167 | unsigned long magic; | ||
4603 | 168 | sourcenotetbl *sources; | ||
4604 | 169 | int n_arches; | ||
4605 | 170 | dpkg_packages **pkgs; | ||
4606 | 171 | char **archname; | ||
4607 | 172 | |||
4608 | 173 | source_note_listlist *undo; | ||
4609 | 174 | }; | ||
4610 | 175 | |||
4611 | 176 | void free_packages(dpkg_packages *pkgs); | ||
4612 | 177 | void free_sources(dpkg_sources *s); | ||
4613 | 178 | |||
4614 | 179 | dpkg_packages *get_architecture(dpkg_sources *srcs, char *arch); | ||
4615 | 180 | |||
4616 | 181 | /* parsing things */ | ||
4617 | 182 | int checkinstallable(dpkg_packages *pkgs, collpackagelist *instoneof); | ||
4618 | 183 | int checkinstallable2(dpkg_packages *pkgs, char *pkgname); | ||
4619 | 184 | satisfieddeplist *checkunsatisfiabledeps(dpkg_packages *pkgs, | ||
4620 | 185 | deplistlist *deps); | ||
4621 | 186 | |||
4622 | 187 | dpkg_sources *read_directory(char *dir, int n_arches, char *archname[]); | ||
4623 | 188 | void write_directory(char *dir, dpkg_sources *srcs); | ||
4624 | 189 | |||
4625 | 190 | void free_source(dpkg_source *s); | ||
4626 | 191 | |||
4627 | 192 | /* adding and deleting and stuff */ | ||
4628 | 193 | dpkg_sources_note *new_sources_note(int n_arches, char **archname); | ||
4629 | 194 | void remove_source(dpkg_sources_note *srcsn, char *name); | ||
4630 | 195 | void upgrade_source(dpkg_sources_note *srcsn, dpkg_source *src); | ||
4631 | 196 | void upgrade_arch(dpkg_sources_note *srcsn, dpkg_source *src, char *arch); | ||
4632 | 197 | void write_notes(char *dir, dpkg_sources_note *srcsn); | ||
4633 | 198 | void free_sources_note(dpkg_sources_note *srcsn); | ||
4634 | 199 | void free_source_note(dpkg_source_note *srcn); | ||
4635 | 200 | void undo_change(dpkg_sources_note *srcsn); | ||
4636 | 201 | int can_undo(dpkg_sources_note *srcsn); | ||
4637 | 202 | void commit_changes(dpkg_sources_note *srcsn); | ||
4638 | 203 | |||
4639 | 204 | int versioncmp(char *left, char *right); | ||
4640 | 205 | int cmpversions(char *left, int op, char *right); | ||
4641 | 206 | |||
4642 | 207 | #endif | ||
4643 | 0 | 208 | ||
4644 | === added file 'update_out/freelist.c' | |||
4645 | --- update_out/freelist.c 1970-01-01 00:00:00 +0000 | |||
4646 | +++ update_out/freelist.c 2015-06-09 16:34:27 +0000 | |||
4647 | @@ -0,0 +1,188 @@ | |||
4648 | 1 | #include <stdio.h> | ||
4649 | 2 | #include <stdlib.h> | ||
4650 | 3 | #include "templates.h" | ||
4651 | 4 | |||
4652 | 5 | typedef unsigned long ul; | ||
4653 | 6 | |||
4654 | 7 | #define SIZE (sizeof(ul) * 8) | ||
4655 | 8 | #define ROUND_DOWN(x) ((x) & ~(SIZE-1)) | ||
4656 | 9 | #define ROUND_UP(x) ROUND_DOWN((x) + (SIZE-1)) | ||
4657 | 10 | #define NEXT_UP(x) ROUND_DOWN((x) + SIZE) | ||
4658 | 11 | #define NEXT_DOWN(x) ROUND_DOWN((x) - 1) | ||
4659 | 12 | |||
4660 | 13 | #define SETBIT(s,p) \ | ||
4661 | 14 | assert( (bits[(s)/SIZE] & (p)) == (setp ? 0 : (p)) ); \ | ||
4662 | 15 | if (setp) bits[(s)/SIZE] |= (p); \ | ||
4663 | 16 | else bits[(s)/SIZE] &= ~(p) | ||
4664 | 17 | |||
4665 | 18 | #define GETBIT(s) (bits[ROUND_DOWN(s)/SIZE] & (1ul << (NEXT_UP(s) - s - 1))) | ||
4666 | 19 | |||
4667 | 20 | size_t count_free_bits_back(ul *bits, size_t s) { | ||
4668 | 21 | size_t cnt = 0; | ||
4669 | 22 | ul w = ROUND_DOWN(s) / SIZE; | ||
4670 | 23 | size_t add = s % SIZE; | ||
4671 | 24 | ul off = (~0ul) << (SIZE - add); | ||
4672 | 25 | ul H, d; | ||
4673 | 26 | |||
4674 | 27 | while ((bits[w] & off) == 0) { | ||
4675 | 28 | cnt += add; | ||
4676 | 29 | add = SIZE; | ||
4677 | 30 | off = ~0ul; | ||
4678 | 31 | if (w == 0) | ||
4679 | 32 | return cnt; | ||
4680 | 33 | w--; | ||
4681 | 34 | } | ||
4682 | 35 | |||
4683 | 36 | H = add; | ||
4684 | 37 | add = 0; | ||
4685 | 38 | while ((d = (H - add) / 2) > 0) { | ||
4686 | 39 | ul offM = (off >> d) & off; | ||
4687 | 40 | if (bits[w] & offM) { | ||
4688 | 41 | off = offM; | ||
4689 | 42 | H = H - d; | ||
4690 | 43 | } else { | ||
4691 | 44 | add = H - d; | ||
4692 | 45 | } | ||
4693 | 46 | } | ||
4694 | 47 | cnt += add; | ||
4695 | 48 | return cnt; | ||
4696 | 49 | } | ||
4697 | 50 | |||
4698 | 51 | size_t count_free_bits_after(ul *bits, size_t s, size_t end) { | ||
4699 | 52 | size_t cnt = 0; | ||
4700 | 53 | ul w = ROUND_DOWN(s) / SIZE; | ||
4701 | 54 | size_t add = SIZE - s % SIZE; | ||
4702 | 55 | ul off = (~0ul) >> (SIZE - add); | ||
4703 | 56 | ul H, d; | ||
4704 | 57 | |||
4705 | 58 | end /= SIZE; | ||
4706 | 59 | |||
4707 | 60 | while ((bits[w] & off) == 0) { | ||
4708 | 61 | cnt += add; | ||
4709 | 62 | add = SIZE; | ||
4710 | 63 | off = ~0ul; | ||
4711 | 64 | w++; | ||
4712 | 65 | if (w == end) | ||
4713 | 66 | return cnt; | ||
4714 | 67 | } | ||
4715 | 68 | |||
4716 | 69 | H = add; | ||
4717 | 70 | add = 0; | ||
4718 | 71 | while ((d = (H - add) / 2) > 0) { | ||
4719 | 72 | ul offM = off << d; | ||
4720 | 73 | if (bits[w] & offM) { | ||
4721 | 74 | off = offM; | ||
4722 | 75 | H = H - d; | ||
4723 | 76 | } else { | ||
4724 | 77 | add = H - d; | ||
4725 | 78 | } | ||
4726 | 79 | } | ||
4727 | 80 | cnt += add; | ||
4728 | 81 | return cnt; | ||
4729 | 82 | } | ||
4730 | 83 | |||
4731 | 84 | void find_long_freebits(ul *bits, size_t s, ul *start, size_t *size) { | ||
4732 | 85 | ul clen = 0; | ||
4733 | 86 | ul bstart = 0, blen = 0; | ||
4734 | 87 | ul i, k; | ||
4735 | 88 | |||
4736 | 89 | for (i = 0; i < s; i++) { | ||
4737 | 90 | if (bits[i] == 0) { | ||
4738 | 91 | clen++; | ||
4739 | 92 | } else { | ||
4740 | 93 | if (clen > blen) { | ||
4741 | 94 | bstart = i - clen; | ||
4742 | 95 | blen = clen; | ||
4743 | 96 | } | ||
4744 | 97 | clen = 0; | ||
4745 | 98 | } | ||
4746 | 99 | } | ||
4747 | 100 | |||
4748 | 101 | if (blen == 0) return; | ||
4749 | 102 | |||
4750 | 103 | bstart *= SIZE; blen *= SIZE; | ||
4751 | 104 | k = count_free_bits_back(bits, bstart); | ||
4752 | 105 | bstart -= k; blen += k; | ||
4753 | 106 | |||
4754 | 107 | blen += count_free_bits_after(bits, bstart + blen, s*SIZE); | ||
4755 | 108 | |||
4756 | 109 | *start = bstart; *size = blen; | ||
4757 | 110 | } | ||
4758 | 111 | |||
4759 | 112 | void mark_bits(ul *bits, ul s, size_t size, int setp) { | ||
4760 | 113 | ul e = s+size; | ||
4761 | 114 | |||
4762 | 115 | ul rds = ROUND_DOWN(s); | ||
4763 | 116 | ul nus = rds + SIZE; | ||
4764 | 117 | ul rue = ROUND_UP(e); | ||
4765 | 118 | |||
4766 | 119 | ul patl = (~0UL) >> (s % SIZE); | ||
4767 | 120 | ul patr = (~0UL) << (rue - e); | ||
4768 | 121 | |||
4769 | 122 | assert(size > 0); | ||
4770 | 123 | |||
4771 | 124 | /* bits[s1..e1] get touched, but bits[s1], bits[e1] only partially | ||
4772 | 125 | * | ||
4773 | 126 | * if s1 == e1, then bits[s1] get touched from [s%SIZE, e%SIZE) | ||
4774 | 127 | * else | ||
4775 | 128 | * bits[s1] gets touched from [s%SIZE, SIZE) | ||
4776 | 129 | * bits[s2..e1) get reset completely | ||
4777 | 130 | * bits[e1] gets touched from [0, e%SIZE) | ||
4778 | 131 | */ | ||
4779 | 132 | |||
4780 | 133 | if (nus >= e) { | ||
4781 | 134 | /* ROUND_DOWN(s) <= s < e <= NEXT_UP(s) */ | ||
4782 | 135 | SETBIT(rds, patl & patr); | ||
4783 | 136 | } else { | ||
4784 | 137 | /* ROUND_DOWN(s) <= s < NEXT_UP(s) <= NEXT_DOWN(e) < e */ | ||
4785 | 138 | ul rde = ROUND_DOWN(e); | ||
4786 | 139 | |||
4787 | 140 | SETBIT(rds, patl); | ||
4788 | 141 | SETBIT(rde, patr); | ||
4789 | 142 | while (nus < rde) { | ||
4790 | 143 | SETBIT(nus, ~0UL); | ||
4791 | 144 | nus += SIZE; | ||
4792 | 145 | } | ||
4793 | 146 | } | ||
4794 | 147 | } | ||
4795 | 148 | |||
4796 | 149 | void print_bits(ul *bits, ul s) { | ||
4797 | 150 | ul i; | ||
4798 | 151 | putchar(' '); | ||
4799 | 152 | for (i = 0; i < s * SIZE; i++) { | ||
4800 | 153 | putchar( GETBIT(i) ? '1' : '0' ); | ||
4801 | 154 | } | ||
4802 | 155 | } | ||
4803 | 156 | |||
4804 | 157 | #ifdef TESTBIN | ||
4805 | 158 | |||
4806 | 159 | #define X 2 | ||
4807 | 160 | int main(void) { | ||
4808 | 161 | ul memory[X]; | ||
4809 | 162 | ul l, r; | ||
4810 | 163 | ul k = 5; | ||
4811 | 164 | |||
4812 | 165 | memset(memory, 0, sizeof(memory)); | ||
4813 | 166 | for (l = 0; l < X*SIZE; l += k) { | ||
4814 | 167 | for (r = 1; l+(r*r) < X*SIZE; r++) { | ||
4815 | 168 | |||
4816 | 169 | printf("%lu %lu (%lu %lu", l, r*r, | ||
4817 | 170 | (unsigned long) count_free_bits_back(memory, X*SIZE), (unsigned long) X*SIZE); | ||
4818 | 171 | mark_bits(memory, l, r*r, 1); | ||
4819 | 172 | printf("; %lu %lu %lu; %lu %lu %lu;): ", | ||
4820 | 173 | (unsigned long) count_free_bits_back(memory, X*SIZE) + l + r*r, | ||
4821 | 174 | (unsigned long) count_free_bits_after(memory, l + r*r, X*SIZE) + l + r*r, | ||
4822 | 175 | (unsigned long) X*SIZE, | ||
4823 | 176 | (unsigned long) count_free_bits_back(memory, l), | ||
4824 | 177 | (unsigned long) count_free_bits_after(memory, 0, X*SIZE), | ||
4825 | 178 | l); | ||
4826 | 179 | print_bits(memory, X); | ||
4827 | 180 | printf("\n"); | ||
4828 | 181 | |||
4829 | 182 | mark_bits(memory, l, r*r, 0); | ||
4830 | 183 | } | ||
4831 | 184 | } | ||
4832 | 185 | |||
4833 | 186 | return 0; | ||
4834 | 187 | } | ||
4835 | 188 | #endif | ||
4836 | 0 | 189 | ||
4837 | === added file 'update_out/freelist.h' | |||
4838 | --- update_out/freelist.h 1970-01-01 00:00:00 +0000 | |||
4839 | +++ update_out/freelist.h 2015-06-09 16:34:27 +0000 | |||
4840 | @@ -0,0 +1,14 @@ | |||
4841 | 1 | |||
4842 | 2 | #ifndef FREELIST_H | ||
4843 | 3 | #define FREELIST_H | ||
4844 | 4 | |||
4845 | 5 | #include <stdlib.h> | ||
4846 | 6 | |||
4847 | 7 | typedef unsigned long flb_t; | ||
4848 | 8 | |||
4849 | 9 | void mark_bits(flb_t *bits, flb_t s, size_t size, int setp); | ||
4850 | 10 | size_t count_free_bits_back(flb_t *bits, size_t s); | ||
4851 | 11 | size_t count_free_bits_after(flb_t *bits, size_t s, size_t end); | ||
4852 | 12 | void find_long_freebits(flb_t *bits, flb_t s, flb_t *start, size_t *size); | ||
4853 | 13 | |||
4854 | 14 | #endif | ||
4855 | 0 | 15 | ||
4856 | === added file 'update_out/index.html' | |||
4857 | --- update_out/index.html 1970-01-01 00:00:00 +0000 | |||
4858 | +++ update_out/index.html 2015-06-09 16:34:27 +0000 | |||
4859 | @@ -0,0 +1,18 @@ | |||
4860 | 1 | <a href="README">README</a><br> | ||
4861 | 2 | <a href="Makefile">Makefile</a><br> | ||
4862 | 3 | <a href="assert.c">assert.c</a><br> | ||
4863 | 4 | <a href="britney-py.c">britney-py.c</a><br> | ||
4864 | 5 | <a href="checklib.c">checklib.c</a><br> | ||
4865 | 6 | <a href="dpkg.c">dpkg.c</a><br> | ||
4866 | 7 | <a href="freelist.c">freelist.c</a><br> | ||
4867 | 8 | <a href="memory.c">memory.c</a><br> | ||
4868 | 9 | <a href="memory2.c">memory2.c</a><br> | ||
4869 | 10 | <a href="memory3.c">memory3.c</a><br> | ||
4870 | 11 | <a href="dpkg-lib.cpp">dpkg-lib.cpp</a><br> | ||
4871 | 12 | <a href="dpkg.h">dpkg.h</a><br> | ||
4872 | 13 | <a href="freelist.h">freelist.h</a><br> | ||
4873 | 14 | <a href="memory.h">memory.h</a><br> | ||
4874 | 15 | <a href="templates.h">templates.h</a><br> | ||
4875 | 16 | <a href="check_out.py">check_out.py</a><br> | ||
4876 | 17 | <a href="check_uptodate.py">check_uptodate.py</a><br> | ||
4877 | 18 | <a href="update_out.py">update_out.py</a><br> | ||
4878 | 0 | 19 | ||
4879 | === added file 'update_out/memory.c' | |||
4880 | --- update_out/memory.c 1970-01-01 00:00:00 +0000 | |||
4881 | +++ update_out/memory.c 2015-06-09 16:34:27 +0000 | |||
4882 | @@ -0,0 +1,389 @@ | |||
4883 | 1 | #include <stdio.h> | ||
4884 | 2 | #include <stdlib.h> | ||
4885 | 3 | |||
4886 | 4 | #include "memory.h" | ||
4887 | 5 | #include "templates.h" | ||
4888 | 6 | #include "freelist.h" | ||
4889 | 7 | |||
4890 | 8 | /**** THEORY | ||
4891 | 9 | * | ||
4892 | 10 | |||
4893 | 11 | So, we have blocks with a freelist | ||
4894 | 12 | |||
4895 | 13 | XXX............XXXXXXX..XXXXX.....XXXXXX...... | ||
4896 | 14 | |||
4897 | 15 | Within a block, we work with segments. A segment is... | ||
4898 | 16 | |||
4899 | 17 | ^..........| | ||
4900 | 18 | |||
4901 | 19 | Every now and then we make sure we've got a decent sized segment. | ||
4902 | 20 | |||
4903 | 21 | We have multiple blocks. They're kept ordered by the size of their | ||
4904 | 22 | current segment. | ||
4905 | 23 | |||
4906 | 24 | **********************************************/ | ||
4907 | 25 | |||
4908 | 26 | #define ALIGN 4 | ||
4909 | 27 | |||
4910 | 28 | #define FLBT_BITS (sizeof(flb_t)*8) | ||
4911 | 29 | #define MEMBLOCKSIZE (1 << 22) | ||
4912 | 30 | #define ALIGNEDSIZE(s) (((s) + ALIGN - 1) / ALIGN * ALIGN) | ||
4913 | 31 | |||
4914 | 32 | struct memblock { | ||
4915 | 33 | struct memblock *next; | ||
4916 | 34 | |||
4917 | 35 | size_t n_bytes; /* index of free char */ | ||
4918 | 36 | size_t size; /* size of block after char */ | ||
4919 | 37 | |||
4920 | 38 | unsigned n_used_chunks; /* number of unfreed blocks */ | ||
4921 | 39 | size_t n_used_bytes; /* number of bytes actually used */ | ||
4922 | 40 | size_t n_productive_bytes; /* number of bytes used usefully */ | ||
4923 | 41 | |||
4924 | 42 | flb_t free[MEMBLOCKSIZE/ALIGN/FLBT_BITS + 1]; | ||
4925 | 43 | unsigned char mem[MEMBLOCKSIZE]; | ||
4926 | 44 | }; | ||
4927 | 45 | typedef struct memblock memblock; | ||
4928 | 46 | |||
4929 | 47 | static memblock *base = NULL; | ||
4930 | 48 | |||
4931 | 49 | #ifdef MDEBUG1 | ||
4932 | 50 | static int valid_memblock_mdebug1(struct memblock *mb) { | ||
4933 | 51 | size_t cnt, i; | ||
4934 | 52 | static int rarity = 0; | ||
4935 | 53 | |||
4936 | 54 | assert(mb->n_bytes + mb->size <= sizeof(mb->mem)); | ||
4937 | 55 | |||
4938 | 56 | if (mb->n_used_chunks == 0) assert(mb->n_bytes == 0); | ||
4939 | 57 | assert(((unsigned long)mb->mem + mb->n_bytes) % ALIGN == 0); | ||
4940 | 58 | |||
4941 | 59 | assert(mb->n_productive_bytes <= mb->n_used_bytes); | ||
4942 | 60 | assert(mb->n_used_bytes + mb->size <= sizeof(mb->mem)); | ||
4943 | 61 | |||
4944 | 62 | #define TWO(k) (1ul << (k)) | ||
4945 | 63 | #define CYCL(k) (~0ul / (1 + TWO(TWO(k)))) | ||
4946 | 64 | |||
4947 | 65 | rarity++; rarity %= 25000; | ||
4948 | 66 | if (rarity != 0) { | ||
4949 | 67 | cnt = mb->n_used_bytes; | ||
4950 | 68 | } else { | ||
4951 | 69 | cnt = 0; | ||
4952 | 70 | for (i = 0; i < sizeof(mb->mem)/ALIGN/FLBT_BITS+1; i++) { | ||
4953 | 71 | unsigned long x = mb->free[i]; | ||
4954 | 72 | size_t s; | ||
4955 | 73 | x = (x & CYCL(0)) + ((x >> TWO(0)) & CYCL(0)); | ||
4956 | 74 | x = (x & CYCL(1)) + ((x >> TWO(1)) & CYCL(1)); | ||
4957 | 75 | for (s = 2; (2u << s) <= FLBT_BITS; s++) { | ||
4958 | 76 | x += x >> TWO(s); | ||
4959 | 77 | x &= CYCL(s); | ||
4960 | 78 | } | ||
4961 | 79 | cnt += x * ALIGN; | ||
4962 | 80 | } | ||
4963 | 81 | } | ||
4964 | 82 | #undef TWO | ||
4965 | 83 | #undef CYCL | ||
4966 | 84 | |||
4967 | 85 | assert(cnt == mb->n_used_bytes); | ||
4968 | 86 | |||
4969 | 87 | return 1; | ||
4970 | 88 | } | ||
4971 | 89 | #endif | ||
4972 | 90 | |||
4973 | 91 | #if MDEBUG3 | ||
4974 | 92 | static int valid_memblock_mdebug3(struct memblock *mb) { | ||
4975 | 93 | size_t offset, step, used; | ||
4976 | 94 | unsigned chunk = 0; | ||
4977 | 95 | |||
4978 | 96 | offset = 0; | ||
4979 | 97 | used = 0; | ||
4980 | 98 | if ((unsigned long)mb->mem % ALIGN != 0) | ||
4981 | 99 | offset = ALIGN - ((unsigned long)mb->mem % ALIGN); | ||
4982 | 100 | |||
4983 | 101 | while(offset < mb->n_bytes) { | ||
4984 | 102 | step = *(size_t*)(mb->mem + offset); | ||
4985 | 103 | assert(step % ALIGN == 0 || step % ALIGN == 1); | ||
4986 | 104 | if (step % ALIGN == 1) step--; /* freed */ | ||
4987 | 105 | else used += step; | ||
4988 | 106 | assert(step > 0); | ||
4989 | 107 | offset += step; | ||
4990 | 108 | chunk++; | ||
4991 | 109 | } | ||
4992 | 110 | |||
4993 | 111 | assert(used == mb->n_used_bytes); | ||
4994 | 112 | |||
4995 | 113 | return 1; | ||
4996 | 114 | } | ||
4997 | 115 | #endif | ||
4998 | 116 | |||
4999 | 117 | inline static int valid_memblock(struct memblock *mb) { | ||
5000 | 118 | (void)mb; |
The diff has been truncated for viewing.