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 

25from daklib.dbconn import * 

26from daklib.config import Config 

27from daklib import daklog 

28 

29import apt_pkg 

30import sys 

31 

32 

33def usage(): 

34 print("""Usage: dak external-overrides COMMAND 

35Modify external overrides. 

36 

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

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

39 

40Commands can use a long or abbreviated form: 

41 

42 import SUITE COMPONENT KEY import external overrides for KEY 

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

44 

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

46 NOTE: Needs --force for untouchable TO 

47 

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

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

50""") 

51 sys.exit() 

52 

53############################################################################# 

54 

55 

56class ExternalOverrideReader: 

57 """ 

58 Parses an external override file 

59 """ 

60 

61 def __init__(self, fh): 

62 self.fh = fh 

63 self.package = None 

64 self.key = None 

65 self.value = [] 

66 

67 def _flush(self): 

68 """ 

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

70 """ 

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

72 self.package = self.key = None 

73 self.value = [] 

74 return res 

75 

76 def __iter__(self): 

77 """ 

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

79 override file 

80 """ 

81 for line in self.fh: 

82 if not line: 

83 continue 

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

85 # Continuation line 

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

87 else: 

88 if self.package is not None: 

89 yield self._flush() 

90 

91 # New line 

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

93 self.value = [value] 

94 

95 if self.package is not None: 

96 yield self._flush() 

97 

98############################################################################# 

99 

100 

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

102 session = DBConn().session() 

103 

104 from_suite = get_suite(from_suite_name, session) 

105 to_suite = get_suite(to_suite_name, session) 

106 

107 if from_suite is None: 

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

109 session.rollback() 

110 return False 

111 if to_suite is None: 

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

113 session.rollback() 

114 return False 

115 

116 if not force and to_suite.untouchable: 

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

118 session.rollback() 

119 return False 

120 

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

122 session.execute(""" 

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

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

125 """, {'from_suite': from_suite.suite_id, 'to_suite': to_suite.suite_id}) 

126 

127 session.commit() 

128 

129 

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

131 session = DBConn().session() 

132 

133 suite = get_suite(suite_name, session) 

134 component = get_component(component_name, session) 

135 

136 if not force and suite.untouchable: 

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

138 session.rollback() 

139 return False 

140 

141 session.query(ExternalOverride).filter_by(suite=suite, component=component, key=key).delete() 

142 

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

144 eo = ExternalOverride() 

145 eo.suite = suite 

146 eo.component = component 

147 eo.package = package 

148 eo.key = key 

149 eo.value = value 

150 session.add(eo) 

151 

152 session.commit() 

153 

154############################################################################# 

155 

156 

157def main(): 

158 cnf = Config() 

159 

160 Arguments = [('h', "help", "External-Overrides::Options::Help"), 

161 ('f', 'force', 'External-Overrides::Options::Force')] 

162 

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

164 try: 

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

166 except KeyError: 

167 Options = {} 

168 

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

170 usage() 

171 

172 force = False 

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

174 force = True 

175 

176 logger = daklog.Logger('external-overrides') 

177 

178 command = args[0] 

179 if command in ('import', 'i'): 

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

181 elif command in ('copy', 'c'): 

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

183 else: 

184 print("E: Unknown commands.") 

185 

186 

187if __name__ == '__main__': 

188 main()