blob: 2ec964d73b93f510eabc2de668684feb6dd470c3 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# Local file checksum cache implementation
2#
3# Copyright (C) 2012 Intel Corporation
4#
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License version 2 as
7# published by the Free Software Foundation.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU General Public License for more details.
13#
14# You should have received a copy of the GNU General Public License along
15# with this program; if not, write to the Free Software Foundation, Inc.,
16# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050018import glob
19import operator
Patrick Williamsc124f4f2015-09-15 14:41:29 -050020import os
21import stat
22import bb.utils
23import logging
24from bb.cache import MultiProcessCache
25
26logger = logging.getLogger("BitBake.Cache")
27
28try:
29 import cPickle as pickle
30except ImportError:
31 import pickle
32 logger.info("Importing cPickle failed. "
33 "Falling back to a very slow implementation.")
34
35
36# mtime cache (non-persistent)
37# based upon the assumption that files do not change during bitbake run
38class FileMtimeCache(object):
39 cache = {}
40
41 def cached_mtime(self, f):
42 if f not in self.cache:
43 self.cache[f] = os.stat(f)[stat.ST_MTIME]
44 return self.cache[f]
45
46 def cached_mtime_noerror(self, f):
47 if f not in self.cache:
48 try:
49 self.cache[f] = os.stat(f)[stat.ST_MTIME]
50 except OSError:
51 return 0
52 return self.cache[f]
53
54 def update_mtime(self, f):
55 self.cache[f] = os.stat(f)[stat.ST_MTIME]
56 return self.cache[f]
57
58 def clear(self):
59 self.cache.clear()
60
61# Checksum + mtime cache (persistent)
62class FileChecksumCache(MultiProcessCache):
63 cache_file_name = "local_file_checksum_cache.dat"
64 CACHE_VERSION = 1
65
66 def __init__(self):
67 self.mtime_cache = FileMtimeCache()
68 MultiProcessCache.__init__(self)
69
70 def get_checksum(self, f):
71 entry = self.cachedata[0].get(f)
72 cmtime = self.mtime_cache.cached_mtime(f)
73 if entry:
74 (mtime, hashval) = entry
75 if cmtime == mtime:
76 return hashval
77 else:
78 bb.debug(2, "file %s changed mtime, recompute checksum" % f)
79
80 hashval = bb.utils.md5_file(f)
81 self.cachedata_extras[0][f] = (cmtime, hashval)
82 return hashval
83
84 def merge_data(self, source, dest):
85 for h in source[0]:
86 if h in dest:
87 (smtime, _) = source[0][h]
88 (dmtime, _) = dest[0][h]
89 if smtime > dmtime:
90 dest[0][h] = source[0][h]
91 else:
92 dest[0][h] = source[0][h]
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050093
94 def get_checksums(self, filelist, pn):
95 """Get checksums for a list of files"""
96
97 def checksum_file(f):
98 try:
99 checksum = self.get_checksum(f)
100 except OSError as e:
101 bb.warn("Unable to get checksum for %s SRC_URI entry %s: %s" % (pn, os.path.basename(f), e))
102 return None
103 return checksum
104
105 def checksum_dir(pth):
106 # Handle directories recursively
107 dirchecksums = []
108 for root, dirs, files in os.walk(pth):
109 for name in files:
110 fullpth = os.path.join(root, name)
111 checksum = checksum_file(fullpth)
112 if checksum:
113 dirchecksums.append((fullpth, checksum))
114 return dirchecksums
115
116 checksums = []
117 for pth in filelist.split():
118 exist = pth.split(":")[1]
119 if exist == "False":
120 continue
121 pth = pth.split(":")[0]
122 if '*' in pth:
123 # Handle globs
124 for f in glob.glob(pth):
125 if os.path.isdir(f):
126 if not os.path.islink(f):
127 checksums.extend(checksum_dir(f))
128 else:
129 checksum = checksum_file(f)
130 checksums.append((f, checksum))
131 elif os.path.isdir(pth):
132 if not os.path.islink(pth):
133 checksums.extend(checksum_dir(pth))
134 else:
135 checksum = checksum_file(pth)
136 checksums.append((pth, checksum))
137
138 checksums.sort(key=operator.itemgetter(1))
139 return checksums