コード例 #1
0
ファイル: cache_file.py プロジェクト: b0bh00d/TCWW
class CacheFile(object):
    def __init__(self, config, path=tempfile.gettempdir()):
        super(CacheFile, self).__init__()
        self.config = config

        # we do not use the agent name in the file.  this
        # would prevent multiple different agents from
        # accessing/updating the same cache file.

        self.cache_file_name = '%s_%s_%s.pickle' % \
                                (config.teamcity.project_name,
                                 config.teamcity.config_name,
                                 config.teamcity.branch_name)

        self.local_file = None
        self.local_file_fp = None
        self.local_file_open_state = FileModes.CLOSED

        self.path = path

        self.ftp = None
        self.ftp_username = None
        self.ftp_password = None
        self.ftp_address = None
        self.ftp_path = None
        self.ftp_display = None

        self.dropbox = None

        temp_folder = tempfile.gettempdir()
        self.local_file = os.path.join(temp_folder, self.cache_file_name)

        if self.path.startswith('ftp://'):
            # open the FTP connection
            if not self._connect_to_ftp():
                print 'Warning: FTP cache folder could not be accessed: "%s"' % self.path
                print 'Warning: Defaulting to local file: "%s"' % self.local_file
            else:
                self.reset()

        elif self.path.startswith('dropbox:'):
            self.dropbox = Dropbox(self.path)
            if not self.dropbox.available():
                print 'Warning: Dropbox could not be accessed: "%s"' % self.path
                print 'Warning: Defaulting to local file: "%s"' % self.local_file
                self.dropbox = None

        else:
            if not os.path.exists(self.path):
                # make sure the full path to the cache folder exists
                try:
                    os.makedirs(self.path)
                except:
                    pass

            if not os.path.exists(self.path):
                print 'Error: Cache folder does not exist: "%s"' % self.path
                sys.exit(1)

            self.local_file = os.path.join(self.path, self.cache_file_name)

    def __del__(self):
        if self.ftp:
            self.ftp.close()
            if os.path.exists(self.local_file):
                os.remove(self.local_file)

    def reset(self):
        if os.path.exists(self.local_file):
            os.remove(self.local_file)

    def open(self, mode=FileModes.READ_ONLY):
        if mode not in [FileModes.READ_ONLY, FileModes.WRITE_ONLY]:
            return None

        self.local_file_open_state = mode
        self.local_file_fp = None

        if self.ftp:
            if not os.path.exists(self.local_file):
                if not self._retrieve_pickle_file():
                    return None

            try:
                self.local_file_fp = open(
                    self.local_file,
                    'rb' if mode == FileModes.READ_ONLY else 'wb')
            except:
                self.local_file_fp = None

        elif self.dropbox:
            self.local_file_fp = self.dropbox.open(self.cache_file_name, mode)

        else:
            try:
                self.local_file_fp = open(
                    self.local_file,
                    'rb' if mode == FileModes.READ_ONLY else 'wb')
            except:
                self.local_file_fp = None

        return self.local_file_fp

    def close(self):
        if self.ftp:
            if (not os.path.exists(
                    self.local_file)) or (not self.local_file_fp):
                return

            try:
                self.local_file_fp.close()
            except:
                pass
            self.local_file_fp = None

            if self.local_file_open_state == FileModes.WRITE_ONLY:
                # upload the (presumably) updated cache file
                if not self._store_pickle_file():
                    print 'Error: Could not store cache file to FTP'
                    sys.exit(1)
                else:
                    self.reset()

        elif self.dropbox:
            self.dropbox.close()
            self.local_file_fp = None

        else:
            try:
                self.local_file_fp.close()
            except:
                pass
            self.local_file_fp = None

    def _retrieve_pickle_file(self):
        if self.ftp:
            files = []
            self.ftp.retrlines('NLST', files.append)
            if self.cache_file_name in files:
                try:
                    self.ftp.retrbinary('RETR %s' % self.cache_file_name,
                                        open(self.local_file, 'wb').write)
                except:
                    return False

        return True

    def _store_pickle_file(self):
        if self.ftp:
            with open(self.local_file, 'rb') as local_file_input:
                try:
                    self.ftp.storbinary('STOR %s' % self.cache_file_name,
                                        local_file_input)
                except:
                    return False

        return True

    def _connect_to_ftp(self):
        result = re.search(r'^ftp:\/\/([\da-z]+):([^\@]+)\@([^\/\s]+)\/(.+)$',
                           self.path)
        if not result:
            return False

        self.ftp_username = result.group(1)
        self.ftp_password = result.group(2)
        self.ftp_address = result.group(3)
        self.ftp_path = result.group(4)

        # take the username/password info out of any displayed value
        self.ftp_display = 'ftp://%s/%s' % (self.ftp_address, self.ftp_path)

        try:
            self.ftp = FTP(self.ftp_address)
        except:
            self.ftp = None
            return False

        try:
            self.ftp.login(self.ftp_username, self.ftp_password)
        except:
            self.ftp.close()
            self.ftp = None
            return False

        #print self.ftp.getwelcome()

        try:
            self.ftp.cwd(self.ftp_path)
        except:
            self.ftp.close()
            self.ftp = None
            return False

        return True

    def __str__(self):
        if self.ftp:
            return '%s/%s' % (self.ftp_display, self.cache_file_name)
        if self.dropbox:
            return str(self.dropbox)
        return os.path.join(os.path.abspath(self.path), self.cache_file_name)