1#! /usr/bin/env python3 

2 

3""" 

4Modify external overrides. 

5 

6@contact: Debian FTP Master <ftpmaster@debian.org> 

7@copyright: 2011 Ansgar Burchardt <ansgar@debian.org> 

8@license: GNU General Public License version 2 or later 

9""" 

10 

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

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

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

14# (at your option) any later version. 

15 

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

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

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

19# GNU General Public License for more details. 

20 

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

22# along with this program; if not, write to the Free Software 

23# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 

24 

25import sys 

26 

27import apt_pkg 

28 

29from daklib.config import Config 

30from daklib.dbconn import DBConn, ExternalOverride, get_component, get_suite 

31 

32 

33def usage(): 

34 print( 

35 """Usage: dak external-overrides COMMAND 

36Modify external overrides. 

37 

38 -h, --help show this help and exit. 

39 -f, --force allow processing of untouchable suites. 

40 

41Commands can use a long or abbreviated form: 

42 

43 import SUITE COMPONENT KEY import external overrides for KEY 

44 i SUITE COMPONENT KEY NOTE: This will replace existing overrides. 

45 

46 copy FROM TO copy external overrides from suite FROM to TO 

47 NOTE: Needs --force for untouchable TO 

48 

49For the 'import' command, external overrides are read from standard input and 

50should be given as lines of the form 'PACKAGE KEY VALUE'. 

51""" 

52 ) 

53 sys.exit() 

54 

55 

56############################################################################# 

57 

58 

59class ExternalOverrideReader: 

60 """ 

61 Parses an external override file 

62 """ 

63 

64 def __init__(self, fh): 

65 self.fh = fh 

66 self.package = None 

67 self.key = None 

68 self.value = [] 

69 

70 def _flush(self): 

71 """ 

72 Return the parsed line that is being built and start parsing a new line 

73 """ 

74 res = self.package, self.key, "\n".join(self.value) 

75 self.package = self.key = None 

76 self.value = [] 

77 return res 

78 

79 def __iter__(self): 

80 """ 

81 returns a (package, key, value) tuple for every entry in the external 

82 override file 

83 """ 

84 for line in self.fh: 

85 if not line: 

86 continue 

87 if line[0] in (" ", "\t"): 

88 # Continuation line 

89 self.value.append(line.rstrip()) 

90 else: 

91 if self.package is not None: 

92 yield self._flush() 

93 

94 # New line 

95 (self.package, self.key, value) = line.rstrip().split(None, 2) 

96 self.value = [value] 

97 

98 if self.package is not None: 

99 yield self._flush() 

100 

101 

102############################################################################# 

103 

104 

105def external_overrides_copy(from_suite_name, to_suite_name, force=False): 

106 session = DBConn().session() 

107 

108 from_suite = get_suite(from_suite_name, session) 

109 to_suite = get_suite(to_suite_name, session) 

110 

111 if from_suite is None: 

112 print("E: source %s not found." % from_suite_name) 

113 session.rollback() 

114 return False 

115 if to_suite is None: 

116 print("E: target %s not found." % to_suite_name) 

117 session.rollback() 

118 return False 

119 

120 if not force and to_suite.untouchable: 

121 print("E: refusing to touch untouchable suite %s (not forced)." % to_suite_name) 

122 session.rollback() 

123 return False 

124 

125 session.query(ExternalOverride).filter_by(suite=to_suite).delete() 

126 session.execute( 

127 """ 

128 INSERT INTO external_overrides (suite, component, package, key, value) 

129 SELECT :to_suite, component, package, key, value FROM external_overrides WHERE suite = :from_suite 

130 """, 

131 {"from_suite": from_suite.suite_id, "to_suite": to_suite.suite_id}, 

132 ) 

133 

134 session.commit() 

135 

136 

137def external_overrides_import(suite_name, component_name, key, file, force=False): 

138 session = DBConn().session() 

139 

140 suite = get_suite(suite_name, session) 

141 component = get_component(component_name, session) 

142 

143 if not force and suite.untouchable: 

144 print("E: refusing to touch untouchable suite %s (not forced)." % suite_name) 

145 session.rollback() 

146 return False 

147 

148 session.query(ExternalOverride).filter_by( 

149 suite=suite, component=component, key=key 

150 ).delete() 

151 

152 for package, key, value in ExternalOverrideReader(file): 

153 eo = ExternalOverride() 

154 eo.suite = suite 

155 eo.component = component 

156 eo.package = package 

157 eo.key = key 

158 eo.value = value 

159 session.add(eo) 

160 

161 session.commit() 

162 

163 

164############################################################################# 

165 

166 

167def main(): 

168 cnf = Config() 

169 

170 Arguments = [ 

171 ("h", "help", "External-Overrides::Options::Help"), 

172 ("f", "force", "External-Overrides::Options::Force"), 

173 ] 

174 

175 args = apt_pkg.parse_commandline(cnf.Cnf, Arguments, sys.argv) 

176 try: 

177 Options = cnf.subtree("External-Overrides::Options") 

178 except KeyError: 

179 Options = {} 

180 

181 if "Help" in Options: 181 ↛ 184line 181 didn't jump to line 184, because the condition on line 181 was never false

182 usage() 

183 

184 force = False 

185 if "Force" in Options and Options["Force"]: 

186 force = True 

187 

188 command = args[0] 

189 if command in ("import", "i"): 

190 external_overrides_import(args[1], args[2], args[3], sys.stdin, force) 

191 elif command in ("copy", "c"): 

192 external_overrides_copy(args[1], args[2], force) 

193 else: 

194 print("E: Unknown commands.") 

195 

196 

197if __name__ == "__main__": 

198 main()