1
2 """
3
4 @author: Fabio Erculiani <lxnay@sabayonlinux.org>
5 @contact: lxnay@sabayonlinux.org
6 @copyright: Fabio Erculiani
7 @license: GPL-2
8
9 B{Entropy Package Manager Client Miscellaneous Interface}.
10
11 """
12
13 import os
14 import sys
15 import shutil
16 import subprocess
17 from entropy.client.interfaces import Client
18 from entropy.exceptions import *
19 from entropy.const import etpConst, etpCache, const_convert_to_rawstring
20 from entropy.output import darkred, darkgreen, red, brown, blue
21 from entropy.tools import getstatusoutput
22 from entropy.i18n import _
23
25
36
38 self.scanfs(dcache = True)
39 self.do_backup(key)
40 source_file = etpConst['systemroot'] + self.scandata[key]['source']
41 dest_file = etpConst['systemroot'] + self.scandata[key]['destination']
42 if os.access(source_file, os.R_OK):
43 shutil.move(source_file, dest_file)
44 self.remove_from_cache(key)
45
47 self.scanfs(dcache = True)
48 source_file = etpConst['systemroot'] + self.scandata[key]['source']
49 if os.path.isfile(source_file) and os.access(source_file, os.W_OK):
50 os.remove(source_file)
51 self.remove_from_cache(key)
52
54 self.scanfs(dcache = True)
55 sys_set_plg_id = \
56 etpConst['system_settings_plugins_ids']['client_plugin']
57 files_backup = self.Entropy.SystemSettings[sys_set_plg_id]['misc']['filesbackup']
58 dest_file = etpConst['systemroot'] + self.scandata[key]['destination']
59 if files_backup and os.path.isfile(dest_file):
60 bcount = 0
61 backupfile = etpConst['systemroot'] + \
62 os.path.dirname(self.scandata[key]['destination']) + \
63 "/._entropy_backup." + str(bcount) + "_" + \
64 os.path.basename(self.scandata[key]['destination'])
65 while os.path.lexists(backupfile):
66 bcount += 1
67 backupfile = etpConst['systemroot'] + \
68 os.path.dirname(self.scandata[key]['destination']) + \
69 "/._entropy_backup." + str(bcount) + "_" + \
70 os.path.basename(self.scandata[key]['destination'])
71 try:
72 shutil.copy2(dest_file, backupfile)
73 except IOError:
74 pass
75
76 - def scanfs(self, dcache = True, quiet = False):
77
78 if dcache:
79
80 if self.scandata != None:
81 return self.scandata
82
83
84 try:
85 z = self.load_cache()
86 if z != None:
87 self.scandata = z
88 return self.scandata
89 except (CacheCorruptionError, KeyError, IOError, OSError,):
90 pass
91
92 scandata = {}
93 counter = 0
94 name_cache = set()
95 client_conf_protect = self.Entropy.get_system_config_protect()
96
97 for path in client_conf_protect:
98
99
100 try:
101 path = path.encode('utf-8')
102 except (UnicodeEncodeError,):
103 path = path.encode(sys.getfilesystemencoding())
104
105 scanfile = False
106 if os.path.isfile(path):
107
108 path = os.path.dirname(path)
109 scanfile = True
110
111 for currentdir, subdirs, files in os.walk(path):
112 for item in files:
113
114 if scanfile:
115 if path != item:
116 continue
117
118 filepath = os.path.join(currentdir, item)
119
120
121 if item.startswith(const_convert_to_rawstring("._cfg")):
122
123
124 number = item[5:9]
125 try:
126 int(number)
127 except ValueError:
128 continue
129 if item[9] != "_":
130 continue
131
132 if filepath in name_cache:
133 continue
134 name_cache.add(filepath)
135
136 mydict = self.generate_dict(filepath)
137 if mydict['automerge']:
138 if not quiet:
139 mytxt = _("Automerging file")
140 self.Entropy.updateProgress(
141 darkred("%s: %s") % (
142 mytxt,
143 darkgreen(etpConst['systemroot'] + mydict['source']),
144 ),
145 importance = 0,
146 type = "info"
147 )
148 if os.path.isfile(etpConst['systemroot']+mydict['source']):
149 try:
150 os.rename(etpConst['systemroot']+mydict['source'],
151 etpConst['systemroot']+mydict['destination'])
152 except (OSError, IOError,) as e:
153 if not quiet:
154 mytxt = "%s :: %s: %s. %s: %s" % (
155 red(_("System Error")),
156 red(_("Cannot automerge file")),
157 brown(etpConst['systemroot'] + mydict['source']),
158 blue("error"),
159 e,
160 )
161 self.Entropy.updateProgress(
162 mytxt,
163 importance = 1,
164 type = "warning"
165 )
166 continue
167 else:
168 counter += 1
169 scandata[counter] = mydict.copy()
170
171 if not quiet:
172 try:
173 self.Entropy.updateProgress(
174 "("+blue(str(counter))+") " + red(" file: ") + \
175 os.path.dirname(filepath) + "/" + os.path.basename(filepath)[10:],
176 importance = 1,
177 type = "info"
178 )
179 except:
180 pass
181
182 self.Cacher.push(etpCache['configfiles'], scandata)
183 self.scandata = scandata.copy()
184 return scandata
185
187 sd = self.Cacher.pop(etpCache['configfiles'])
188 if not isinstance(sd, dict):
189 raise CacheCorruptionError("CacheCorruptionError")
190
191 try:
192 name_cache = set()
193
194 for x in sd:
195 mysource = sd[x]['source']
196
197 if mysource in name_cache:
198 sd.pop(x)
199 continue
200 if not os.path.isfile(etpConst['systemroot']+mysource):
201 raise CacheCorruptionError("CacheCorruptionError")
202 name_cache.add(mysource)
203
204 return sd
205 except (KeyError, EOFError, IOError,):
206 raise CacheCorruptionError("CacheCorruptionError")
207
209 self.scanfs(dcache = True, quiet = quiet)
210 keys = list(self.scandata.keys())
211 try:
212 for key in keys:
213 if self.scandata[key]['source'] == filepath[len(etpConst['systemroot']):]:
214 del self.scandata[key]
215 except:
216 pass
217
218 if keys:
219 keys = sorted(keys)
220 index = keys[-1]
221 else:
222 index = 0
223 index += 1
224 mydata = self.generate_dict(filepath)
225 self.scandata[index] = mydata.copy()
226 self.Cacher.push(etpCache['configfiles'], self.scandata)
227
229 self.scanfs(dcache = True)
230 try:
231 del self.scandata[key]
232 except:
233 pass
234 self.Cacher.push(etpCache['configfiles'], self.scandata)
235 return self.scandata
236
238
239 item = os.path.basename(filepath)
240 currentdir = os.path.dirname(filepath)
241 tofile = item[10:]
242 number = item[5:9]
243 try:
244 int(number)
245 except:
246 mytxt = _("Invalid config file number")
247 raise InvalidDataType("InvalidDataType: %s '0000->9999'." % (mytxt,))
248 tofilepath = currentdir+"/"+tofile
249 mydict = {}
250 mydict['revision'] = number
251 mydict['destination'] = tofilepath[len(etpConst['systemroot']):]
252 mydict['source'] = filepath[len(etpConst['systemroot']):]
253 mydict['automerge'] = False
254 if not os.path.isfile(tofilepath):
255 mydict['automerge'] = True
256 if (not mydict['automerge']):
257
258 try:
259 if not os.path.lexists(filepath):
260 return mydict
261 if os.path.islink(filepath):
262
263 if not os.path.exists(filepath):
264 return mydict
265 result = getstatusoutput('diff -Nua "%s" "%s" | grep "^[+-][^+-]" | grep -v \'# .Header:.*\'' % (filepath, tofilepath,))[1]
266 if not result:
267 mydict['automerge'] = True
268 except:
269 pass
270
271 if (not mydict['automerge']):
272 try:
273 if not os.path.lexists(filepath):
274 return mydict
275 if os.path.islink(filepath):
276
277 if not os.path.exists(filepath):
278 return mydict
279 result = subprocess.call('diff -Bbua "%s" "%s" | egrep \'^[+-]\' | egrep -v \'^[+-][\t ]*#|^--- |^\+\+\+ \' | egrep -qv \'^[-+][\t ]*$\'' % (filepath, tofilepath,), shell = True)
280 if result == 1:
281 mydict['automerge'] = True
282 except:
283 pass
284 return mydict
285