def list_installed_files(self, allow_fail=False):
def _md5(path):<EOL><INDENT>f = open(path, '<STR_LIT:rb>')<EOL>try:<EOL><INDENT>content = f.read()<EOL><DEDENT>finally:<EOL><INDENT>f.close()<EOL><DEDENT>return hashlib.md5(content).hexdigest()<EOL><DEDENT>def _size(path):<EOL><INDENT>return os.stat(path).st_size<EOL><DEDENT>record_path = os.path.join(self.path, '<STR_LIT>')<EOL>result = []<EOL>if os.path.exists(record_path):<EOL><INDENT>with codecs.open(record_path, '<STR_LIT:r>', encoding='<STR_LIT:utf-8>') as f:<EOL><INDENT>for line in f:<EOL><INDENT>line = line.strip()<EOL>p = os.path.normpath(os.path.join(self.path, line))<EOL>if not os.path.exists(p):<EOL><INDENT>logger.warning('<STR_LIT>', p)<EOL>if allow_fail or p.endswith(('<STR_LIT>', '<STR_LIT>')):<EOL><INDENT>continue<EOL><DEDENT><DEDENT>if not os.path.isdir(p):<EOL><INDENT>result.append((p, _md5(p), _size(p)))<EOL><DEDENT><DEDENT><DEDENT>result.append((record_path, None, None))<EOL><DEDENT>return result<EOL>
Iterates over the ``installed-files.txt`` entries and returns a tuple
``(path, hash, size)`` for each line.

:returns: a list of (path, hash, size)