util: Raise FilePermissionDeniedError if the file cannot be

read by the current user.

Whitespace, variable name cleanups
This commit is contained in:
Ozan Çağlayan
2011-06-07 07:43:37 +00:00
parent 7f5d97a984
commit ff87a7716d
+34 -31
View File
@@ -1,6 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# #
# Copyright (C) 2005-2010, TUBITAK/UEKAE # Copyright (C) 2005-2011, TUBITAK/UEKAE
# #
# This program is free software; you can redistribute it and/or modify it under # This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free # the terms of the GNU General Public License as published by the Free
@@ -53,6 +53,9 @@ class Error(pisi.Error):
class FileError(Error): class FileError(Error):
pass pass
class FilePermissionDeniedError(Error):
pass
######################### #########################
# spec validation utility # # spec validation utility #
@@ -78,22 +81,22 @@ def unzip(seq):
def concat(l): def concat(l):
"""Concatenate a list of lists.""" """Concatenate a list of lists."""
return reduce( operator.concat, l ) return reduce(operator.concat, l )
def strlist(l): def strlist(l):
"""Concatenate string reps of l's elements.""" """Concatenate string reps of l's elements."""
return "".join(map(lambda x: str(x) + ' ', l)) return "".join(map(lambda x: str(x) + ' ', l))
def multisplit(str, chars): def multisplit(_str, chars):
"""Split str with any of the chars.""" """Split str with any of the chars."""
l = [str] l = [_str]
for c in chars: for c in chars:
l = concat(map(lambda x:x.split(c), l)) l = concat(map(lambda x:x.split(c), l))
return l return l
def same(l): def same(l):
"""Check if all elements of a sequence are equal.""" """Check if all elements of a sequence are equal."""
if len(l)==0: if len(l) == 0:
return True return True
else: else:
last = l.pop() last = l.pop()
@@ -305,7 +308,6 @@ def parentpath(a, sep = os.path.sep):
def parenturi(a): def parenturi(a):
return parentpath(a, '/') return parentpath(a, '/')
# but this one is necessary
def subpath(a, b): def subpath(a, b):
"""Find if path a is before b in the directory tree.""" """Find if path a is before b in the directory tree."""
return prefix(splitpath(a), splitpath(b)) return prefix(splitpath(a), splitpath(b))
@@ -320,9 +322,7 @@ def removepathprefix(prefix, path):
def join_path(a, *p): def join_path(a, *p):
"""Join two or more pathname components. """Join two or more pathname components.
Python os.path.join cannot handle '/' at the start of latter components. Python os.path.join cannot handle '/' at the start of latter components.
""" """
path = a path = a
for b in p: for b in p:
@@ -337,10 +337,10 @@ def join_path(a, *p):
# File/Directory Related Functions # # File/Directory Related Functions #
#################################### ####################################
def check_file(file, mode = os.F_OK): def check_file(_file, mode = os.F_OK):
"""Shorthand to check if a file exists.""" """Shorthand to check if a file exists."""
if not os.access(file, mode): if not os.access(_file, mode):
raise FileError("File " + file + " not found") raise FileError("File " + _file + " not found")
return True return True
def ensure_dirs(path): def ensure_dirs(path):
@@ -353,14 +353,14 @@ def clean_dir(path):
if os.path.exists(path): if os.path.exists(path):
shutil.rmtree(path) shutil.rmtree(path)
def creation_time(file): def creation_time(_file):
"""Return the creation time of the given file.""" """Return the creation time of the given file."""
if check_file(file): if check_file(_file):
import time import time
st = os.stat(file) st = os.stat(_file)
return time.localtime(st.st_ctime) return time.localtime(st.st_ctime)
def dir_size(dir): def dir_size(_dir):
"""Calculate the size of files under a directory.""" """Calculate the size of files under a directory."""
# It's really hard to give an approximate value for package's # It's really hard to give an approximate value for package's
# installed size. Gettin a sum of all files' sizes if far from # installed size. Gettin a sum of all files' sizes if far from
@@ -368,15 +368,15 @@ def dir_size(dir):
# better solution :(. # better solution :(.
# Not really, du calculates size on disk, this is much better -- exa # Not really, du calculates size on disk, this is much better -- exa
if os.path.exists(dir) and (not os.path.isdir(dir) and not os.path.islink(dir)): if os.path.exists(_dir) and (not os.path.isdir(_dir) and not os.path.islink(_dir)):
#so, this is not a directory but file.. #so, this is not a directory but file..
return os.path.getsize(dir) return os.path.getsize(_dir)
if os.path.islink(dir): if os.path.islink(_dir):
return long(len(read_link(dir))) return long(len(read_link(_dir)))
def sizes(): def sizes():
for root, dirs, files in os.walk(dir): for root, dirs, files in os.walk(_dir):
yield sum([os.path.getsize(join_path(root, name)) for name in files if not os.path.islink(join_path(root, name))]) yield sum([os.path.getsize(join_path(root, name)) for name in files if not os.path.islink(join_path(root, name))])
return sum(sizes()) return sum(sizes())
@@ -431,12 +431,12 @@ def calculate_hash(path):
# We pad them with zeroes, thus hash will be stable # We pad them with zeroes, thus hash will be stable
clean_ar_timestamps(path) clean_ar_timestamps(path)
value = sha1_file(path) value = sha1_file(path)
return (path, value) return (path, value)
def get_file_hashes(top, excludePrefix=None, removePrefix=None): def get_file_hashes(top, excludePrefix=None, removePrefix=None):
"""Yield (path, hash) tuples for given directory tree. """Yield (path, hash) tuples for given directory tree.
Generator function iterates over a toplevel path and returns the Generator function iterates over a toplevel path and returns the
(filePath, sha1Hash) tuples for all files. If excludePrefixes list (filePath, sha1Hash) tuples for all files. If excludePrefixes list
is given as a parameter, function will exclude the filePaths is given as a parameter, function will exclude the filePaths
@@ -452,20 +452,20 @@ def get_file_hashes(top, excludePrefix=None, removePrefix=None):
return False return False
temp = os.path.dirname(temp) temp = os.path.dirname(temp)
return True return True
# single file/symlink case # single file/symlink case
if not os.path.isdir(top) or os.path.islink(top): if not os.path.isdir(top) or os.path.islink(top):
if is_included(top): if is_included(top):
yield calculate_hash(top) yield calculate_hash(top)
return return
for root, dirs, files in os.walk(top): for root, dirs, files in os.walk(top):
# Hash files and file symlinks # Hash files and file symlinks
for name in files: for name in files:
path = os.path.join(root, name) path = os.path.join(root, name)
if is_included(path): if is_included(path):
yield calculate_hash(path) yield calculate_hash(path)
# Hash symlink dirs # Hash symlink dirs
# os.walk doesn't enter them, we don't want to follow them either # os.walk doesn't enter them, we don't want to follow them either
# but their name and hashes must be reported # but their name and hashes must be reported
@@ -475,7 +475,7 @@ def get_file_hashes(top, excludePrefix=None, removePrefix=None):
if os.path.islink(path): if os.path.islink(path):
if is_included(path): if is_included(path):
yield calculate_hash(path) yield calculate_hash(path)
# Hash empty dir # Hash empty dir
# Discussed in bug #340 # Discussed in bug #340
if len(files) == 0 and len(dirs) == 0: if len(files) == 0 and len(dirs) == 0:
@@ -495,7 +495,7 @@ def sha1_file(filename):
# Broken links can cause problem! # Broken links can cause problem!
try: try:
m = hashlib.sha1() m = hashlib.sha1()
f = file(filename, 'rb') f = open(filename, 'rb')
while True: while True:
# 256 KB seems ideal for speed/memory tradeoff # 256 KB seems ideal for speed/memory tradeoff
# It wont get much faster with bigger blocks, but # It wont get much faster with bigger blocks, but
@@ -510,8 +510,12 @@ def sha1_file(filename):
# we wont have two allocated blocks with same size # we wont have two allocated blocks with same size
del block del block
return m.hexdigest() return m.hexdigest()
except IOError: except IOError, e:
raise FileError(_("Cannot calculate SHA1 hash of %s") % filename) if e.errno == 13:
# Permission denied, the file doesn't have read permissions, skip
raise FilePermissionDeniedError(_("You don't have necessary permissions to read %s") % filename)
else:
raise FileError(_("Cannot calculate SHA1 hash of %s") % filename)
def sha1_data(data): def sha1_data(data):
"""Calculate sha1 hash of given data.""" """Calculate sha1 hash of given data."""
@@ -655,9 +659,8 @@ def package_filename(name, version, release, distro_id=None, arch=None):
def parse_package_name_legacy(package_name): def parse_package_name_legacy(package_name):
"""Separate package name and version string for package formats <= 1.1. """Separate package name and version string for package formats <= 1.1.
example: tasma-1.0.3-5-2 -> (tasma, 1.0.3-5-2) example: tasma-1.0.3-5-2 -> (tasma, 1.0.3-5-2)
""" """
# We should handle package names like 855resolution # We should handle package names like 855resolution
name = [] name = []