]> git.decadent.org.uk Git - dak.git/blob - daklib/changesutils.py
Fix up output path for security
[dak.git] / daklib / changesutils.py
1 #!/usr/bin/env python
2 # vim:set et ts=4 sw=4:
3
4 """Utilities for handling changes files
5
6 @contact: Debian FTP Master <ftpmaster@debian.org>
7 @copyright: 2001, 2002, 2003, 2004, 2005, 2006  James Troup <james@nocrew.org>
8 @copyright: 2009 Joerg Jaspert <joerg@debian.org>
9 @copyright: 2009 Frank Lichtenheld <djpig@debian.org>
10 @license: GNU General Public License version 2 or later
11 """
12 # This program is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU General Public License as published by
14 # the Free Software Foundation; either version 2 of the License, or
15 # (at your option) any later version.
16
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21
22 # You should have received a copy of the GNU General Public License
23 # along with this program; if not, write to the Free Software
24 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25
26 ################################################################################
27
28 import copy
29 import os
30 import stat
31 import apt_pkg
32
33 from daklib.dbconn import *
34 from daklib.queue import *
35 from daklib import utils
36 from daklib.config import Config
37
38 ################################################################################
39
40 __all__ = []
41
42 ################################################################################
43
44 def indiv_sg_compare (a, b):
45     """Sort by source name, source, version, 'have source', and
46        finally by filename."""
47     # Sort by source version
48     q = apt_pkg.VersionCompare(a["version"], b["version"])
49     if q:
50         return -q
51
52     # Sort by 'have source'
53     a_has_source = a["architecture"].get("source")
54     b_has_source = b["architecture"].get("source")
55     if a_has_source and not b_has_source:
56         return -1
57     elif b_has_source and not a_has_source:
58         return 1
59
60     return cmp(a["filename"], b["filename"])
61
62 __all__.append('indiv_sg_compare')
63
64 ############################################################
65
66 def sg_compare (a, b):
67     a = a[1]
68     b = b[1]
69     """Sort by have note, source already in database and time of oldest upload."""
70     # Sort by have note
71     a_note_state = a["note_state"]
72     b_note_state = b["note_state"]
73     if a_note_state < b_note_state:
74         return -1
75     elif a_note_state > b_note_state:
76         return 1
77     # Sort by source already in database (descending)
78     source_in_database = cmp(a["source_in_database"], b["source_in_database"])
79     if source_in_database:
80         return -source_in_database
81
82     # Sort by time of oldest upload
83     return cmp(a["oldest"], b["oldest"])
84
85 __all__.append('sg_compare')
86
87 def sort_changes(changes_files, session, binaries = None):
88     """Sort into source groups, then sort each source group by version,
89     have source, filename.  Finally, sort the source groups by have
90     note, time of oldest upload of each source upload."""
91     if len(changes_files) == 1:
92         return changes_files
93
94     sorted_list = []
95     cache = {}
96     # Read in all the .changes files
97     for filename in changes_files:
98         u = Upload()
99         try:
100             u.pkg.changes_file = filename
101             u.load_changes(filename)
102             u.update_subst()
103             cache[filename] = copy.copy(u.pkg.changes)
104             cache[filename]["filename"] = filename
105         except:
106             sorted_list.append(filename)
107             break
108     # Divide the .changes into per-source groups
109     per_source = {}
110     for filename in cache.keys():
111         source = cache[filename]["source"]
112         if not per_source.has_key(source):
113             per_source[source] = {}
114             per_source[source]["list"] = []
115         per_source[source]["list"].append(cache[filename])
116     # Determine oldest time and have note status for each source group
117     for source in per_source.keys():
118         q = session.query(DBSource).filter_by(source = source).all()
119         per_source[source]["source_in_database"] = binaries and -(len(q)>0) or len(q)>0
120         source_list = per_source[source]["list"]
121         first = source_list[0]
122         oldest = os.stat(first["filename"])[stat.ST_MTIME]
123         have_note = 0
124         for d in per_source[source]["list"]:
125             mtime = os.stat(d["filename"])[stat.ST_MTIME]
126             if mtime < oldest:
127                 oldest = mtime
128             have_note += has_new_comment(d["source"], d["version"], session)
129         per_source[source]["oldest"] = oldest
130         if not have_note:
131             per_source[source]["note_state"] = 0; # none
132         elif have_note < len(source_list):
133             per_source[source]["note_state"] = 1; # some
134         else:
135             per_source[source]["note_state"] = 2; # all
136         per_source[source]["list"].sort(indiv_sg_compare)
137     per_source_items = per_source.items()
138     per_source_items.sort(sg_compare)
139     for i in per_source_items:
140         for j in i[1]["list"]:
141             sorted_list.append(j["filename"])
142     return sorted_list
143
144 __all__.append('sort_changes')
145
146 ################################################################################
147
148 def changes_to_queue(upload, srcqueue, destqueue, session):
149     """Move a changes file to a different queue and mark as approved for the
150        source queue"""
151
152     try:
153         chg = session.query(DBChange).filter_by(changesname=os.path.basename(upload.pkg.changes_file)).one()
154     except NoResultFound:
155         return False
156
157     chg.approved_for_id = srcqueue.policy_queue_id
158
159     for f in chg.files:
160         # update the changes_pending_files row
161         f.queue = destqueue
162         # Only worry about unprocessed files
163         if not f.processed:
164             utils.move(os.path.join(srcqueue.path, f.filename), destqueue.path, perms=int(destqueue.perms, 8))
165
166     utils.move(os.path.join(srcqueue.path, upload.pkg.changes_file), destqueue.path, perms=int(destqueue.perms, 8))
167     chg.in_queue = destqueue
168     session.commit()
169
170     return True
171
172 __all__.append('changes_to_queue')
173
174 def new_accept(upload, dry_run, session):
175     print "ACCEPT"
176
177     if not dry_run:
178         cnf = Config()
179
180         (summary, short_summary) = upload.build_summaries()
181         destqueue = get_policy_queue('newstage', session)
182
183         srcqueue = get_policy_queue_from_path(upload.pkg.directory, session)
184
185         if not srcqueue:
186             # Assume NEW and hope for the best
187             srcqueue = get_policy_queue('new', session)
188
189         changes_to_queue(upload, srcqueue, destqueue, session)
190
191 __all__.append('new_accept')