1
2 '''
3 # DESCRIPTION:
4 # Entropy Object Oriented Interface
5
6 Copyright (C) 2007-2009 Fabio Erculiani
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 '''
22
23 import os
24 import sys
25 import shutil
26 import subprocess
27 from entropy.client.interfaces import Client
28 from entropy.exceptions import *
29 from entropy.const import etpConst, etpCache
30 from entropy.output import darkred, darkgreen, red, brown, blue
31 from entropy.tools import getstatusoutput
32 from entropy.i18n import _
33
35
46
48 self.scanfs(dcache = True)
49 self.do_backup(key)
50 source_file = etpConst['systemroot'] + self.scandata[key]['source']
51 dest_file = etpConst['systemroot'] + self.scandata[key]['destination']
52 if os.access(source_file, os.R_OK):
53 shutil.move(source_file, dest_file)
54 self.remove_from_cache(key)
55
57 self.scanfs(dcache = True)
58 source_file = etpConst['systemroot'] + self.scandata[key]['source']
59 if os.access(source_file, os.F_OK) and os.access(source_file, os.W_OK):
60 os.remove(source_file)
61 self.remove_from_cache(key)
62
64 self.scanfs(dcache = True)
65 sys_set_plg_id = \
66 etpConst['system_settings_plugins_ids']['client_plugin']
67 files_backup = self.Entropy.SystemSettings[sys_set_plg_id]['misc']['filesbackup']
68 dest_file = etpConst['systemroot'] + self.scandata[key]['destination']
69 if files_backup and os.path.isfile(dest_file):
70 bcount = 0
71 backupfile = etpConst['systemroot'] + \
72 os.path.dirname(self.scandata[key]['destination']) + \
73 "/._entropy_backup." + unicode(bcount) + "_" + \
74 os.path.basename(self.scandata[key]['destination'])
75 while os.path.lexists(backupfile):
76 bcount += 1
77 backupfile = etpConst['systemroot'] + \
78 os.path.dirname(self.scandata[key]['destination']) + \
79 "/._entropy_backup." + unicode(bcount) + "_" + \
80 os.path.basename(self.scandata[key]['destination'])
81 try:
82 shutil.copy2(dest_file, backupfile)
83 except IOError:
84 pass
85
86 - def scanfs(self, dcache = True, quiet = False):
87
88 if dcache:
89
90 if self.scandata != None:
91 return self.scandata
92
93
94 try:
95 z = self.load_cache()
96 if z != None:
97 self.scandata = z
98 return self.scandata
99 except (CacheCorruptionError, KeyError, IOError, OSError,):
100 pass
101
102 scandata = {}
103 counter = 0
104 name_cache = set()
105 client_conf_protect = self.Entropy.get_system_config_protect()
106
107 for path in client_conf_protect:
108
109
110 path = path.encode(sys.getfilesystemencoding())
111
112 scanfile = False
113 if os.path.isfile(path):
114
115 path = os.path.dirname(path)
116 scanfile = True
117
118 for currentdir,subdirs,files in os.walk(path):
119 for item in files:
120
121 if scanfile:
122 if path != item:
123 continue
124
125 filepath = os.path.join(currentdir,item)
126 if item.startswith("._cfg"):
127
128
129 number = item[5:9]
130 try:
131 int(number)
132 except ValueError:
133 continue
134 if item[9] != "_":
135 continue
136
137 if filepath in name_cache:
138 continue
139 name_cache.add(filepath)
140
141 mydict = self.generate_dict(filepath)
142 if mydict['automerge']:
143 if not quiet:
144 mytxt = _("Automerging file")
145 self.Entropy.updateProgress(
146 darkred("%s: %s") % (
147 mytxt,
148 darkgreen(etpConst['systemroot'] + mydict['source']),
149 ),
150 importance = 0,
151 type = "info"
152 )
153 if os.path.isfile(etpConst['systemroot']+mydict['source']):
154 try:
155 os.rename(etpConst['systemroot']+mydict['source'],
156 etpConst['systemroot']+mydict['destination'])
157 except (OSError, IOError,), e:
158 if not quiet:
159 mytxt = "%s :: %s: %s. %s: %s" % (
160 red(_("System Error")),
161 red(_("Cannot automerge file")),
162 brown(etpConst['systemroot'] + mydict['source']),
163 blue("error"),
164 e,
165 )
166 self.Entropy.updateProgress(
167 mytxt,
168 importance = 1,
169 type = "warning"
170 )
171 continue
172 else:
173 counter += 1
174 scandata[counter] = mydict.copy()
175
176 if not quiet:
177 try:
178 self.Entropy.updateProgress(
179 "("+blue(str(counter))+") " + red(" file: ") + \
180 os.path.dirname(filepath) + "/" + os.path.basename(filepath)[10:],
181 importance = 1,
182 type = "info"
183 )
184 except:
185 pass
186
187 self.Cacher.push(etpCache['configfiles'],scandata)
188 self.scandata = scandata.copy()
189 return scandata
190
192 sd = self.Cacher.pop(etpCache['configfiles'])
193 if not isinstance(sd,dict):
194 raise CacheCorruptionError("CacheCorruptionError")
195
196 try:
197 name_cache = set()
198
199 for x in sd:
200 mysource = sd[x]['source']
201
202 if mysource in name_cache:
203 sd.pop(x)
204 continue
205 if not os.path.isfile(etpConst['systemroot']+mysource):
206 raise CacheCorruptionError("CacheCorruptionError")
207 name_cache.add(mysource)
208
209 return sd
210 except (KeyError,EOFError,IOError,):
211 raise CacheCorruptionError("CacheCorruptionError")
212
214 self.scanfs(dcache = True, quiet = quiet)
215 keys = self.scandata.keys()
216 try:
217 for key in keys:
218 if self.scandata[key]['source'] == filepath[len(etpConst['systemroot']):]:
219 del self.scandata[key]
220 except:
221 pass
222
223 if keys:
224 keys = sorted(keys)
225 index = keys[-1]
226 else:
227 index = 0
228 index += 1
229 mydata = self.generate_dict(filepath)
230 self.scandata[index] = mydata.copy()
231 self.Cacher.push(etpCache['configfiles'],self.scandata)
232
234 self.scanfs(dcache = True)
235 try:
236 del self.scandata[key]
237 except:
238 pass
239 self.Cacher.push(etpCache['configfiles'],self.scandata)
240 return self.scandata
241
243
244 item = os.path.basename(filepath)
245 currentdir = os.path.dirname(filepath)
246 tofile = item[10:]
247 number = item[5:9]
248 try:
249 int(number)
250 except:
251 mytxt = _("Invalid config file number")
252 raise InvalidDataType("InvalidDataType: %s '0000->9999'." % (mytxt,))
253 tofilepath = currentdir+"/"+tofile
254 mydict = {}
255 mydict['revision'] = number
256 mydict['destination'] = tofilepath[len(etpConst['systemroot']):]
257 mydict['source'] = filepath[len(etpConst['systemroot']):]
258 mydict['automerge'] = False
259 if not os.path.isfile(tofilepath):
260 mydict['automerge'] = True
261 if (not mydict['automerge']):
262
263 try:
264 if not os.path.lexists(filepath):
265 return mydict
266 if os.path.islink(filepath):
267
268 if not os.path.exists(filepath):
269 return mydict
270 result = getstatusoutput('diff -Nua "%s" "%s" | grep "^[+-][^+-]" | grep -v \'# .Header:.*\'' % (filepath,tofilepath,))[1]
271 if not result:
272 mydict['automerge'] = True
273 except:
274 pass
275
276 if (not mydict['automerge']):
277 try:
278 if not os.path.lexists(filepath):
279 return mydict
280 if os.path.islink(filepath):
281
282 if not os.path.exists(filepath):
283 return mydict
284 result = subprocess.call('diff -Bbua "%s" "%s" | egrep \'^[+-]\' | egrep -v \'^[+-][\t ]*#|^--- |^\+\+\+ \' | egrep -qv \'^[-+][\t ]*$\'' % (filepath,tofilepath,), shell = True)
285 if result == 1:
286 mydict['automerge'] = True
287 except:
288 pass
289 return mydict
290