# Copyright (C) 2004 Nicolas Delon # All Rights Reserved # # This file is part of the Prelude program. # # 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 Software Foundation; either version 2, or (at your option) # any later version. # # This program 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 General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; see the file COPYING. If not, write to # the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. from stat import * import time import os import os.path import urllib import glob import Digests, FileSummary def file_is_pattern(filename): for c in filename: if c in "*?[]": return True return False class InputFile: def __init__(self, filename, properties): self.filename = filename self.properties = properties def __str__(self): return "%s (%#x)" % (self.filename, self.properties) class InputLocalFile(InputFile): def __init__(self, filename, properties, stats): InputFile.__init__(self, os.path.normpath(filename), properties) self._stats = stats def getSummary(self): file = FileSummary.LocalFileSummary(self.filename, self.properties, self._stats) if not S_ISDIR(self._stats[ST_MODE]) and not S_ISLNK(self._stats[ST_MODE]): if self.properties & FileSummary.MD5: file.setMD5Digest(Digests.md5_file_digest(self.filename)) if self.properties & FileSummary.SHA: file.setSHADigest(Digests.sha_file_digest(self.filename)) return file class InputRemoteFile(InputFile): def getSummary(self): self._handle = urllib.urlopen(self.filename) file = FileSummary.RemoteFileSummary(self.filename, self.properties) file.setSize(int(self._handle.headers["Content-Length"])) if self.properties & FileSummary.MD5: file.setMD5Digest(Digests.md5_content_digest(self._handle.read())) if self.properties & FileSummary.SHA: file.setSHADigest(Digests.sha_content_digest(self._handle.read())) return file class InputHTTPFile(InputRemoteFile): def getSummary(self): file = InputRemoteFile.getSummary(self) file.setMtime(time.mktime(self._handle.info().getdate("Last-Modified"))) return file class InputFileGroup: "Abstract base class for InputLocalFileGroup and InputRemoteFileGroup" def __init__(self, name, recursive, properties): self.name = name self.recursive = recursive if properties is None: properties = self.DEFAULT_PROPERTIES self.properties = properties class InputLocalFileGroup(InputFileGroup): DEFAULT_PROPERTIES = FileSummary.INODE | FileSummary.MODE | FileSummary.LINKS | \ FileSummary.UID | FileSummary.GID | FileSummary.SIZE | FileSummary.MTIME | \ FileSummary.CTIME | FileSummary.MD5 def __expand(self, filename): stats = os.lstat(filename) ret = [ InputLocalFile(filename, self.properties, stats) ] # if S_ISLNK(stats[ST_MODE]): # target = os.readlink(filename) # if target[0] != "/": # target = os.path.dirname(filename) + "/" + target # ret += self.__expand(target) if self.recursive and S_ISDIR(stats[ST_MODE]): dir = filename for filename in os.listdir(dir): ret += self.__expand("%s/%s" % (dir, filename)) return ret def expand(self): ret = [ ] name = os.path.expandvars(os.path.expanduser(self.name)) if file_is_pattern(name) and not os.path.exists(name): for filename in glob.glob(name): ret += self.__expand(filename) else: ret += self.__expand(name) return ret class InputRemoteFileGroup(InputFileGroup): DEFAULT_PROPERTIES = FileSummary.SIZE | FileSummary.MD5 def expand(self): return [ InputRemoteFile(self.name, self.properties) ] class InputHTTPFileGroup(InputRemoteFileGroup): DEFAULT_PROPERTIES = FileSummary.MTIME | FileSummary.SIZE | FileSummary.MD5 def expand(self): return [ InputHTTPFile(self.name, self.properties) ] def new_file_group(name, recursive, properties=None): l = name.split("://") if len(l) == 1 or l[0] == "file": return InputLocalFileGroup(name, recursive, properties) if l[0] == "http": return InputHTTPFileGroup(name, recursive, properties) return InputRemoteFileGroup(name, recursive, properties)