Browse Source

add mtime/etag support to PyFS publisher

main
Ryan Kelly 13 years ago
parent
commit
12c679572a
1 changed files with 48 additions and 4 deletions
  1. +48
    -4
      hyde/ext/publishers/pyfs.py

+ 48
- 4
hyde/ext/publishers/pyfs.py View File

@@ -1,9 +1,18 @@
""" """
Contains classes and utilities that help publishing a hyde website to Contains classes and utilities that help publishing a hyde website to
a filesystem using PyFilesystem FS objects. a filesystem using PyFilesystem FS objects.

This publisher provides an easy way to publish to FTP, SFTP, WebDAV or other
servers by specifying a PyFS filesystem URL. For example, the following
are valid URLs that can be used with this publisher:

ftp://my.server.com/~username/my_blog/
dav:https://username:password@my.server.com/path/to/my/site

""" """


import getpass import getpass
import hashlib


from hyde.fs import File, Folder from hyde.fs import File, Folder
from hyde.publisher import Publisher from hyde.publisher import Publisher
@@ -23,6 +32,10 @@ class PyFS(Publisher):
def initialize(self, settings): def initialize(self, settings):
self.settings = settings self.settings = settings
self.url = settings.url self.url = settings.url
self.check_mtime = getattr(settings,"check_mtime",False)
self.check_etag = getattr(settings,"check_etag",False)
if self.check_etag and not isinstance(self.check_etag,basestring):
raise ValueError("check_etag must name the etag algorithm")
self.prompt_for_credentials() self.prompt_for_credentials()
self.fs = fsopendir(self.url) self.fs = fsopendir(self.url)


@@ -39,17 +52,48 @@ class PyFS(Publisher):
def publish(self): def publish(self):
super(PyFS, self).publish() super(PyFS, self).publish()
deploy_fs = OSFS(self.site.config.deploy_root_path.path) deploy_fs = OSFS(self.site.config.deploy_root_path.path)
for (dirnm,filenms) in deploy_fs.walk():
for (dirnm,local_filenms) in deploy_fs.walk():
logger.info("Making directory: %s",dirnm) logger.info("Making directory: %s",dirnm)
self.fs.makedir(dirnm,allow_recreate=True) self.fs.makedir(dirnm,allow_recreate=True)
for filenm in filenms:
remote_fileinfos = self.fs.listdirinfo(dirnm,files_only=True)
# Process each local file, to see if it needs updating.
for filenm in local_filenms:
filepath = pathjoin(dirnm,filenm) filepath = pathjoin(dirnm,filenm)
# Try to find an existing remote file, to compare metadata.
for (nm,info) in remote_fileinfos:
if nm == filenm:
break
else:
info = {}
# Skip it if the etags match
if self.check_etag and "etag" in info:
with deploy_fs.open(filepath,"rb") as f:
local_etag = self._calculate_etag(f)
if info["etag"] == local_etag:
logger.info("Skipping file [etag]: %s",filepath)
continue
# Skip it if the mtime is more recent remotely.
if self.check_mtime and "modified_time" in info:
local_mtime = deploy_fs.getinfo(filepath)["modified_time"]
if info["modified_time"] > local_mtime:
logger.info("Skipping file [mtime]: %s",filepath)
continue
# Upload it to the remote filesystem.
logger.info("Uploading file: %s",filepath) logger.info("Uploading file: %s",filepath)
with deploy_fs.open(filepath,"rb") as f: with deploy_fs.open(filepath,"rb") as f:
self.fs.setcontents(filepath,f) self.fs.setcontents(filepath,f)
for filenm in self.fs.listdir(dirnm,files_only=True):
# Process each remote file, to see if it needs deleting.
for (filenm,info) in remote_fileinfos:
filepath = pathjoin(dirnm,filenm) filepath = pathjoin(dirnm,filenm)
if filenm not in filenms:
if filenm not in local_filenms:
logger.info("Removing file: %s",filepath) logger.info("Removing file: %s",filepath)
self.fs.remove(filepath) self.fs.remove(filepath)


def _calculate_etag(self,f):
hasher = getattr(hashlib,self.check_etag.lower())()
data = f.read(1024*64)
while data:
hasher.update(data)
data = f.read(1024*64)
return hasher.hexdigest()


Loading…
Cancel
Save