1#! /usr/bin/env python3 

2# 

3# Copyright (C) 2012, Ansgar Burchardt <ansgar@debian.org> 

4# 

5# This program is free software; you can redistribute it and/or modify 

6# it under the terms of the GNU General Public License as published by 

7# the Free Software Foundation; either version 2 of the License, or 

8# (at your option) any later version. 

9# 

10# This program is distributed in the hope that it will be useful, 

11# but WITHOUT ANY WARRANTY; without even the implied warranty of 

12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

13# GNU General Public License for more details. 

14# 

15# You should have received a copy of the GNU General Public License along 

16# with this program; if not, write to the Free Software Foundation, Inc., 

17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 

18 

19import apt_pkg 

20import os 

21import sys 

22 

23from daklib.dbconn import * 

24import daklib.archive 

25import daklib.config 

26import daklib.daklog 

27import daklib.upload 

28import daklib.regexes 

29 

30 

31def usage(): 

32 print("""Usage: 

33 

34dak import <suite> <component> <files...> 

35dak import -D|--dump <file> <suite> <component> 

36dak import -E|--export-dump <suite> <component> 

37 

38WARNING: This command does no sanity checks. Only use it on trusted packages. 

39 

40Options: 

41 -h, --help: show this help message 

42 -a, --add-overrides: add missing overrides automatically 

43 -c, --changed-by: Changed-By for imported source packages 

44 (default: maintainer) 

45 -D, --dump <file>: Import all files listed in <file>. The format 

46 is described below. 

47 -E, --export-dump: Export list of files in the format required 

48 by dak import --dump. 

49 -s, --ignore-signature: ignore signature for imported source packages 

50 

51File format used by --dump: 

52 

53 <filename>:<md5>:<sha1>:<sha256>:[<fingerprint>]:[<changed-by>] 

54""") 

55 

56 

57def import_source(log, transaction, suite, component, directory, hashed_file, 

58 fingerprint=None, changed_by=None, 

59 keyrings=None, require_signature=True, add_overrides=False): 

60 if keyrings is None: 

61 keyrings = [] 

62 filename = hashed_file.filename 

63 session = transaction.session 

64 

65 source = daklib.upload.Source(directory, [hashed_file], keyrings, require_signature) 

66 if source.valid_signature: 

67 fingerprint = session.query(Fingerprint).filter_by(fingerprint=source.primary_fingerprint).first() 

68 if changed_by is None: 

69 changed_by = source.dsc['Maintainer'] 

70 db_changed_by = get_or_set_maintainer(changed_by, session) 

71 

72 transaction.install_source(directory, source, suite, component, db_changed_by, fingerprint=fingerprint) 

73 log.log(['import-source', suite.suite_name, component.component_name, filename]) 

74 

75 if add_overrides and not session.query(Override).filter_by(suite=suite.get_overridesuite(), component=component, package=source.dsc['Source']).join(OverrideType).filter(OverrideType.overridetype == 'dsc').first(): 

76 overridetype = session.query(OverrideType).filter_by(overridetype='dsc').one() 

77 overridesuite = suite.get_overridesuite() 

78 section_name = 'misc' 

79 if component.component_name != 'main': 

80 section_name = "{0}/{1}".format(component.component_name, section_name) 

81 section = session.query(Section).filter_by(section=section_name).one() 

82 priority = session.query(Priority).filter_by(priority='optional').one() 

83 

84 override = Override(package=source.dsc['Source'], suite=overridesuite, component=component, 

85 section=section, priority=priority, overridetype=overridetype) 

86 session.add(override) 

87 log.log(['add-source-override', suite.suite_name, component.component_name, source.dsc['Source'], section.section, priority.priority]) 

88 

89 

90def import_binary(log, transaction, suite, component, directory, hashed_file, fingerprint=None, add_overrides=False): 

91 filename = hashed_file.filename 

92 session = transaction.session 

93 

94 binary = daklib.upload.Binary(directory, hashed_file) 

95 transaction.install_binary(directory, binary, suite, component, fingerprint=fingerprint) 

96 log.log(['import-binary', suite.suite_name, component.component_name, filename]) 

97 

98 if add_overrides and not session.query(Override).filter_by(suite=suite.get_overridesuite(), component=component, package=binary.control['Package']).join(OverrideType).filter(OverrideType.overridetype == binary.type).first(): 

99 overridetype = session.query(OverrideType).filter_by(overridetype=binary.type).one() 

100 overridesuite = suite.get_overridesuite() 

101 section = session.query(Section).filter_by(section=binary.control['Section']).one() 

102 priority = session.query(Priority).filter_by(priority=binary.control.get('Priority', 'optional')).one() 

103 

104 override = Override(package=binary.control['Package'], suite=overridesuite, component=component, 

105 section=section, priority=priority, overridetype=overridetype) 

106 session.add(override) 

107 log.log(['add-binary-override', suite.suite_name, component.component_name, binary.control['Package'], section.section, priority.priority]) 

108 

109 

110def import_file(log, transaction, suite, component, directory, hashed_file, 

111 fingerprint=None, changed_by=None, keyrings=None, require_signature=True, 

112 add_overrides=False): 

113 filename = hashed_file.filename 

114 if daklib.regexes.re_file_binary.match(filename): 

115 import_binary(log, transaction, suite, component, directory, hashed_file, 

116 fingerprint=fingerprint, add_overrides=add_overrides) 

117 elif daklib.regexes.re_file_dsc.match(filename): 

118 import_source(log, transaction, suite, component, directory, hashed_file, 

119 fingerprint=fingerprint, changed_by=changed_by, keyrings=keyrings, 

120 require_signature=require_signature, add_overrides=add_overrides) 

121 else: 

122 raise Exception('File is neither source nor binary package: {0}'.format(filename)) 

123 

124 

125def import_dump(log, transaction, suite, component, fh, 

126 keyrings=None, require_signature=True, add_overrides=False): 

127 session = transaction.session 

128 for line in fh: 

129 path, size, md5, sha1, sha256, fpr, changed_by = line.strip().split(':', 6) 

130 

131 if not changed_by: 

132 changed_by = None 

133 fingerprint = None 

134 if fpr: 

135 fingerprint = session.query(Fingerprint).filter_by(fingerprint=fpr).first() 

136 if fingerprint is None: 

137 print('W: {0}: unknown fingerprint {1}'.format(filename, fpr)) 

138 

139 directory, filename = os.path.split(os.path.abspath(path)) 

140 hashed_file = daklib.upload.HashedFile(filename, int(size), md5, sha1, sha256) 

141 hashed_file.check(directory) 

142 

143 import_file(log, transaction, suite, component, directory, hashed_file, 

144 fingerprint=fingerprint, changed_by=changed_by, 

145 keyrings=keyrings, require_signature=require_signature, add_overrides=add_overrides) 

146 

147 transaction.commit() 

148 

149 

150_export_query = r""" 

151WITH 

152tmp AS 

153 (SELECT 1 AS order, s.file AS file_id, s.sig_fpr AS fingerprint_id, s.changedby AS changed_by, sa.suite AS suite_id 

154 FROM source s 

155 JOIN src_associations sa ON sa.source = s.id 

156 UNION 

157 SELECT 2 AS order, b.file AS file_id, b.sig_fpr AS fingerprint_id, NULL, ba.suite AS suite_id 

158 FROM binaries b 

159 JOIN bin_associations ba ON ba.bin = b.id 

160 ) 

161 

162SELECT 

163 f.filename, f.size::TEXT, f.md5sum, f.sha1sum, f.sha256sum, COALESCE(fpr.fingerprint, ''), COALESCE(m.name, '') 

164FROM files f 

165JOIN tmp ON f.id = tmp.file_id 

166JOIN suite ON suite.id = tmp.suite_id 

167JOIN files_archive_map fam ON fam.file_id = f.id AND fam.archive_id = suite.archive_id 

168LEFT JOIN fingerprint fpr ON fpr.id = tmp.fingerprint_id 

169LEFT JOIN maintainer m ON m.id = tmp.changed_by 

170 

171WHERE 

172 suite.id = :suite_id 

173 AND fam.component_id = :component_id 

174 

175ORDER BY tmp.order, f.filename; 

176""" 

177 

178 

179def export_dump(transaction, suite, component): 

180 session = transaction.session 

181 query = session.execute(_export_query, 

182 {'suite_id': suite.suite_id, 

183 'component_id': component.component_id}) 

184 for row in query: 

185 print(":".join(row)) 

186 

187 

188def main(argv=None): 

189 if argv is None: 189 ↛ 192line 189 didn't jump to line 192

190 argv = sys.argv 

191 

192 arguments = [ 

193 ('h', 'help', 'Import::Options::Help'), 

194 ('a', 'add-overrides', 'Import::Options::AddOverrides'), 

195 ('c', 'changed-by', 'Import::Options::ChangedBy', 'HasArg'), 

196 ('D', 'dump', 'Import::Options::Dump', 'HasArg'), 

197 ('E', 'export-dump', 'Import::Options::Export'), 

198 ('s', 'ignore-signature', 'Import::Options::IgnoreSignature'), 

199 ] 

200 

201 cnf = daklib.config.Config() 

202 cnf['Import::Options::Dummy'] = '' 

203 argv = apt_pkg.parse_commandline(cnf.Cnf, arguments, argv) 

204 options = cnf.subtree('Import::Options') 

205 

206 if 'Help' in options or len(argv) < 2: 206 ↛ 210line 206 didn't jump to line 210, because the condition on line 206 was never false

207 usage() 

208 sys.exit(0) 

209 

210 suite_name = argv[0] 

211 component_name = argv[1] 

212 

213 add_overrides = options.find_b('AddOverrides') 

214 require_signature = not options.find_b('IgnoreSignature') 

215 changed_by = options.find('ChangedBy') or None 

216 

217 log = daklib.daklog.Logger('import') 

218 

219 with daklib.archive.ArchiveTransaction() as transaction: 

220 session = transaction.session 

221 suite = session.query(Suite).filter_by(suite_name=suite_name).one() 

222 component = session.query(Component).filter_by(component_name=component_name).one() 

223 keyrings = session.query(Keyring).filter_by(active=True).order_by(Keyring.priority) 

224 keyring_files = [k.keyring_name for k in keyrings] 

225 

226 dump = options.find('Dump') or None 

227 if options.find_b('Export'): 

228 export_dump(transaction, suite, component) 

229 transaction.rollback() 

230 elif dump is not None: 

231 with open(dump, 'r') as fh: 

232 import_dump(log, transaction, suite, component, fh, keyring_files, 

233 require_signature=require_signature, add_overrides=add_overrides) 

234 transaction.commit() 

235 else: 

236 files = argv[2:] 

237 for f in files: 

238 directory, filename = os.path.split(os.path.abspath(f)) 

239 hashed_file = daklib.upload.HashedFile.from_file(directory, filename) 

240 import_file(log, transaction, suite, component, directory, hashed_file, 

241 changed_by=changed_by, 

242 keyrings=keyring_files, require_signature=require_signature, 

243 add_overrides=add_overrides) 

244 transaction.commit() 

245 

246 log.close() 

247 

248 

249if __name__ == '__main__': 

250 main()