1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
# -*- Mode: Python -*-
# GObject-Introspection - a framework for introspecting GObject libraries
# Copyright (C) 2008 Johan Dahlin
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the
# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
# Boston, MA 02111-1307, USA.
#
import errno
import cPickle
import hashlib
import os
import tempfile
def _get_cachedir():
homedir = os.environ.get('HOME')
if homedir is None:
return None
if not os.path.exists(homedir):
return None
cachedir = os.path.join(homedir, '.cache')
if not os.path.exists(cachedir):
os.mkdir(cachedir, 0755)
scannerdir = os.path.join(cachedir, 'g-ir-scanner')
if not os.path.exists(scannerdir):
os.mkdir(scannerdir, 0755)
# If it exists and is a file, don't cache at all
elif not os.path.isdir(scannerdir):
return None
return scannerdir
class CacheStore(object):
def __init__(self):
try:
self._directory = _get_cachedir()
except OSError, e:
if e.errno != errno.EPERM:
raise
self._directory = None
def _get_filename(self, filename):
# If we couldn't create the directory we're probably
# on a read only home directory where we just disable
# the cache all together.
if self._directory is None:
return
hexdigest = hashlib.sha1(filename).hexdigest()
return os.path.join(self._directory, hexdigest)
def _cache_is_valid(self, store_filename, filename):
return (os.stat(store_filename).st_mtime >=
os.stat(filename).st_mtime)
def _remove_filename(filename):
try:
os.unlink(filename)
except IOError, e:
# Permission denied
if e.errno == errno.EACCES:
return
else:
raise
except OSError, e:
# File does not exist
if e.errno == errno.ENOENT:
return
else:
raise
def store(self, filename, data):
store_filename = self._get_filename(filename)
if store_filename is None:
return
if (os.path.exists(store_filename) and
self._cache_is_valid(store_filename, filename)):
return None
tmp_fd, tmp_filename = tempfile.mkstemp(prefix='g-ir-scanner-cache-')
try:
cPickle.dump(data, os.fdopen(tmp_fd, 'w'))
except IOError, e:
# No space left on device
if e.errno == errno.ENOSPC:
self._remove_filename(tmp_filename)
return
else:
raise
try:
os.rename(tmp_filename, store_filename)
except OSError, e:
# Permission denied
if e.errno == errno.EACCES:
self._remove_filename(tmp_filename)
else:
raise
def load(self, filename):
store_filename = self._get_filename(filename)
if store_filename is None:
return
try:
fd = open(store_filename)
except IOError, e:
if e.errno == errno.ENOENT:
return None
else:
raise
if not self._cache_is_valid(store_filename, filename):
return None
try:
data = cPickle.load(fd)
except (EOFError, ValueError, cPickle.BadPickleGet):
# Broken cache entry, remove it
self._remove_filename(store_filename)
data = None
return data
|