65983393f5e91fa974158fdcb1443b93980f1c01
[portage.git] / pym / portage / cache / flat_list.py
1 from portage.cache import fs_template
2 from portage.cache import cache_errors
3 import errno, os, stat
4
5 # store the current key order *here*.
6 class database(fs_template.FsBased):
7
8         autocommits = True
9
10         # do not screw with this ordering. _eclasses_ needs to be last
11         auxdbkey_order=('DEPEND', 'RDEPEND', 'SLOT', 'SRC_URI',
12                 'RESTRICT',  'HOMEPAGE',  'LICENSE', 'DESCRIPTION',
13                 'KEYWORDS',  'IUSE', 'CDEPEND',
14                 'PDEPEND',   'PROVIDE', 'EAPI', 'PROPERTIES')
15
16         def __init__(self, label, auxdbkeys, **config):
17                 super(database,self).__init__(label, auxdbkeys, **config)
18                 self._base = os.path.join(self._base, 
19                         self.label.lstrip(os.path.sep).rstrip(os.path.sep))
20
21                 if len(self._known_keys) > len(self.auxdbkey_order) + 2:
22                         raise Exception("less ordered keys then auxdbkeys")
23                 if not os.path.exists(self._base):
24                         self._ensure_dirs()
25
26
27         def _getitem(self, cpv):
28                 d = {}
29                 try:
30                         myf = open(os.path.join(self._base, cpv),"r")
31                         for k,v in zip(self.auxdbkey_order, myf):
32                                 d[k] = v.rstrip("\n")
33                 except (OSError, IOError),e:
34                         if errno.ENOENT == e.errno:
35                                 raise KeyError(cpv)
36                         raise cache_errors.CacheCorruption(cpv, e)
37
38                 try:
39                         d["_mtime_"] = long(os.fstat(myf.fileno()).st_mtime)
40                 except OSError, e:      
41                         myf.close()
42                         raise cache_errors.CacheCorruption(cpv, e)
43                 myf.close()
44                 return d
45
46
47         def _setitem(self, cpv, values):
48                 s = cpv.rfind("/")
49                 fp=os.path.join(self._base,cpv[:s],".update.%i.%s" % (os.getpid(), cpv[s+1:]))
50                 try:    myf=open(fp, "w")
51                 except (OSError, IOError), e:
52                         if errno.ENOENT == e.errno:
53                                 try:
54                                         self._ensure_dirs(cpv)
55                                         myf=open(fp,"w")
56                                 except (OSError, IOError),e:
57                                         raise cache_errors.CacheCorruption(cpv, e)
58                         else:
59                                 raise cache_errors.CacheCorruption(cpv, e)
60                 
61
62                 for x in self.auxdbkey_order:
63                         myf.write(values.get(x,"")+"\n")
64
65                 myf.close()
66                 self._ensure_access(fp, mtime=values["_mtime_"])
67                 #update written.  now we move it.
68                 new_fp = os.path.join(self._base,cpv)
69                 try:    os.rename(fp, new_fp)
70                 except (OSError, IOError), e:
71                         os.remove(fp)
72                         raise cache_errors.CacheCorruption(cpv, e)
73
74
75         def _delitem(self, cpv):
76                 try:
77                         os.remove(os.path.join(self._base,cpv))
78                 except OSError, e:
79                         if errno.ENOENT == e.errno:
80                                 raise KeyError(cpv)
81                         else:
82                                 raise cache_errors.CacheCorruption(cpv, e)
83
84
85         def __contains__(self, cpv):
86                 return os.path.exists(os.path.join(self._base, cpv))
87
88
89         def __iter__(self):
90                 """generator for walking the dir struct"""
91                 dirs = [self._base]
92                 len_base = len(self._base)
93                 while len(dirs):
94                         for l in os.listdir(dirs[0]):
95                                 if l.endswith(".cpickle"):
96                                         continue
97                                 p = os.path.join(dirs[0],l)
98                                 st = os.lstat(p)
99                                 if stat.S_ISDIR(st.st_mode):
100                                         dirs.append(p)
101                                         continue
102                                 yield p[len_base+1:]
103                         dirs.pop(0)
104
105
106         def commit(self):       pass