import os
import re

from pipeline.conf import settings
from pipeline.storage import storage
from pipeline.utils import to_class


class Versioning(object):
    def __init__(self, verbose=False):
        self.verbose = verbose

    def versioner(self):
        return to_class(settings.PIPELINE_VERSIONING)(self)
    versioner = property(versioner)

    def version(self, paths):
        return getattr(self.versioner, 'version')(paths)

    def version_from_file(self, path, filename):
        filename = settings.PIPELINE_VERSION_PLACEHOLDER.join([re.escape(part) for part in filename.split(settings.PIPELINE_VERSION_PLACEHOLDER)])
        regex = re.compile(r'^%s$' % self.output_filename(filename, r'([A-Za-z0-9]+)'))
        versions = []
        for f in sorted(storage.listdir(path)[1], reverse=True):
            version = regex.match(f)
            if version and version.groups():
                versions.append(version.group(1))
        versions.sort()
        return versions[-1]

    def output_filename(self, filename, version):
        if settings.PIPELINE_VERSION and version is not None:
            return filename.replace(settings.PIPELINE_VERSION_PLACEHOLDER,
                version)
        else:
            return filename.replace(settings.PIPELINE_VERSION_PLACEHOLDER,
                settings.PIPELINE_VERSION_DEFAULT)

    def need_update(self, output_file, paths):
        version = self.version(paths)
        output_file = self.output_filename(output_file, version)
        if not storage.exists(output_file):
            return True, version
        return getattr(self.versioner, 'need_update')(output_file, paths, version)

    def cleanup(self, filename):
        if not (settings.PIPELINE_VERSION and settings.PIPELINE_VERSION_REMOVE_OLD):
            return  # Nothing to delete here
        path = os.path.dirname(filename)
        filename = settings.PIPELINE_VERSION_PLACEHOLDER.join([re.escape(part) for part in filename.split(settings.PIPELINE_VERSION_PLACEHOLDER)])
        regex = re.compile(r'^%s$' % os.path.basename(self.output_filename(filename, r'([A-Za-z0-9]+)')))
        if storage.exists(path):
            for f in storage.listdir(path)[1]:
                if regex.match(f):
                    if self.verbose:
                        print "Removing outdated file %s" % f
                    storage.delete(os.path.join(path, f))


class VersioningBase(object):
    def __init__(self, versioning):
        self.versioning = versioning

    def output_filename(self, filename, version):
        return self.versioning.output_filename(filename, version)

    def version(self, source_files):
        raise NotImplementedError

    def needs_update(self, output_file, paths, version):
        raise NotImplementedError


class VersioningError(Exception):
    """This exception is raised when version creation fails"""
    pass

@@ -1855,16 +1855,62 @@
 lename)%0A
+        filename = os.path.basename(filename)%0A
         
@@ -2085,33 +2085,16 @@
 %5E%25s$' %25 
-os.path.basename(
 self.out
@@ -2135,17 +2135,16 @@
 -9%5D+)'))
-)
 %0A       
@@ -2148,31 +2148,11 @@
     
-if storage.exists(path)
+try
 :%0A  
@@ -2388,16 +2388,167 @@
 th, f))%0A
+        except EnvironmentError:%0A            # We can't use exists() first because some backends (S3) have no concept of directories.%0A            pass%0A
 %0A%0Aclass 

fix cleanup for all storages