Package entropy :: Package client :: Module misc

Source Code for Module entropy.client.misc

  1  # -*- coding: utf-8 -*- 
  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 
 20  from entropy.output import darkred, darkgreen, red, brown, blue 
 21  from entropy.tools import getstatusoutput 
 22  from entropy.i18n import _ 
 23   
24 -class FileUpdates:
25
26 - def __init__(self, EquoInstance):
27 if not isinstance(EquoInstance,Client): 28 mytxt = _("A valid Client instance or subclass is needed") 29 raise IncorrectParameter("IncorrectParameter: %s" % (mytxt,)) 30 self.Entropy = EquoInstance 31 from entropy.cache import EntropyCacher 32 from entropy.core.settings.base import SystemSettings 33 self.Cacher = EntropyCacher() 34 self.SystemSettings = SystemSettings() 35 self.scandata = None
36
37 - def merge_file(self, key):
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
46 - def remove_file(self, key):
47 self.scanfs(dcache = True) 48 source_file = etpConst['systemroot'] + self.scandata[key]['source'] 49 if os.access(source_file, os.F_OK) and os.access(source_file, os.W_OK): 50 os.remove(source_file) 51 self.remove_from_cache(key)
52
53 - def do_backup(self, key):
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." + unicode(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." + unicode(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 # can we load cache? 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 # this avoids encoding issues hands down 100 path = path.encode(sys.getfilesystemencoding()) 101 # it's a file? 102 scanfile = False 103 if os.path.isfile(path): 104 # find inside basename 105 path = os.path.dirname(path) 106 scanfile = True 107 108 for currentdir,subdirs,files in os.walk(path): 109 for item in files: 110 111 if scanfile: 112 if path != item: 113 continue 114 115 filepath = os.path.join(currentdir,item) 116 if item.startswith("._cfg"): 117 118 # further check then 119 number = item[5:9] 120 try: 121 int(number) 122 except ValueError: 123 continue # not a valid etc-update file 124 if item[9] != "_": # no valid format provided 125 continue 126 127 if filepath in name_cache: 128 continue # skip, already done 129 name_cache.add(filepath) 130 131 mydict = self.generate_dict(filepath) 132 if mydict['automerge']: 133 if not quiet: 134 mytxt = _("Automerging file") 135 self.Entropy.updateProgress( 136 darkred("%s: %s") % ( 137 mytxt, 138 darkgreen(etpConst['systemroot'] + mydict['source']), 139 ), 140 importance = 0, 141 type = "info" 142 ) 143 if os.path.isfile(etpConst['systemroot']+mydict['source']): 144 try: 145 os.rename(etpConst['systemroot']+mydict['source'], 146 etpConst['systemroot']+mydict['destination']) 147 except (OSError, IOError,), e: 148 if not quiet: 149 mytxt = "%s :: %s: %s. %s: %s" % ( 150 red(_("System Error")), 151 red(_("Cannot automerge file")), 152 brown(etpConst['systemroot'] + mydict['source']), 153 blue("error"), 154 e, 155 ) 156 self.Entropy.updateProgress( 157 mytxt, 158 importance = 1, 159 type = "warning" 160 ) 161 continue 162 else: 163 counter += 1 164 scandata[counter] = mydict.copy() 165 166 if not quiet: 167 try: 168 self.Entropy.updateProgress( 169 "("+blue(str(counter))+") " + red(" file: ") + \ 170 os.path.dirname(filepath) + "/" + os.path.basename(filepath)[10:], 171 importance = 1, 172 type = "info" 173 ) 174 except: 175 pass # possible encoding issues 176 # store data 177 self.Cacher.push(etpCache['configfiles'],scandata) 178 self.scandata = scandata.copy() 179 return scandata
180
181 - def load_cache(self):
182 sd = self.Cacher.pop(etpCache['configfiles']) 183 if not isinstance(sd,dict): 184 raise CacheCorruptionError("CacheCorruptionError") 185 # quick test if data is reliable 186 try: 187 name_cache = set() 188 189 for x in sd: 190 mysource = sd[x]['source'] 191 # filter dupies 192 if mysource in name_cache: 193 sd.pop(x) 194 continue 195 if not os.path.isfile(etpConst['systemroot']+mysource): 196 raise CacheCorruptionError("CacheCorruptionError") 197 name_cache.add(mysource) 198 199 return sd 200 except (KeyError,EOFError,IOError,): 201 raise CacheCorruptionError("CacheCorruptionError")
202
203 - def add_to_cache(self, filepath, quiet = False):
204 self.scanfs(dcache = True, quiet = quiet) 205 keys = self.scandata.keys() 206 try: 207 for key in keys: 208 if self.scandata[key]['source'] == filepath[len(etpConst['systemroot']):]: 209 del self.scandata[key] 210 except: 211 pass 212 # get next counter 213 if keys: 214 keys = sorted(keys) 215 index = keys[-1] 216 else: 217 index = 0 218 index += 1 219 mydata = self.generate_dict(filepath) 220 self.scandata[index] = mydata.copy() 221 self.Cacher.push(etpCache['configfiles'],self.scandata)
222
223 - def remove_from_cache(self, key):
224 self.scanfs(dcache = True) 225 try: 226 del self.scandata[key] 227 except: 228 pass 229 self.Cacher.push(etpCache['configfiles'],self.scandata) 230 return self.scandata
231
232 - def generate_dict(self, filepath):
233 234 item = os.path.basename(filepath) 235 currentdir = os.path.dirname(filepath) 236 tofile = item[10:] 237 number = item[5:9] 238 try: 239 int(number) 240 except: 241 mytxt = _("Invalid config file number") 242 raise InvalidDataType("InvalidDataType: %s '0000->9999'." % (mytxt,)) 243 tofilepath = currentdir+"/"+tofile 244 mydict = {} 245 mydict['revision'] = number 246 mydict['destination'] = tofilepath[len(etpConst['systemroot']):] 247 mydict['source'] = filepath[len(etpConst['systemroot']):] 248 mydict['automerge'] = False 249 if not os.path.isfile(tofilepath): 250 mydict['automerge'] = True 251 if (not mydict['automerge']): 252 # is it trivial? 253 try: 254 if not os.path.lexists(filepath): # if file does not even exist 255 return mydict 256 if os.path.islink(filepath): 257 # if it's broken, skip diff and automerge 258 if not os.path.exists(filepath): 259 return mydict 260 result = getstatusoutput('diff -Nua "%s" "%s" | grep "^[+-][^+-]" | grep -v \'# .Header:.*\'' % (filepath,tofilepath,))[1] 261 if not result: 262 mydict['automerge'] = True 263 except: 264 pass 265 # another test 266 if (not mydict['automerge']): 267 try: 268 if not os.path.lexists(filepath): # if file does not even exist 269 return mydict 270 if os.path.islink(filepath): 271 # if it's broken, skip diff and automerge 272 if not os.path.exists(filepath): 273 return mydict 274 result = subprocess.call('diff -Bbua "%s" "%s" | egrep \'^[+-]\' | egrep -v \'^[+-][\t ]*#|^--- |^\+\+\+ \' | egrep -qv \'^[-+][\t ]*$\'' % (filepath,tofilepath,), shell = True) 275 if result == 1: 276 mydict['automerge'] = True 277 except: 278 pass 279 return mydict
280