Skip to content

Commit

Permalink
Improve '.cfignore' handle
Browse files Browse the repository at this point in the history
  • Loading branch information
Ben Einaudi committed Jul 11, 2019
1 parent ec8343d commit fa479de
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 25 deletions.
38 changes: 38 additions & 0 deletions main/cloudfoundry_client/operations/push/cf_ignore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import fnmatch
import logging
import os

_logger = logging.getLogger(__name__)


class CfIgnore(object):
def __init__(self, application_path):
ignore_file_path = os.path.join(application_path, '.cfignore')
self.ignore_items = []
if os.path.isfile(ignore_file_path):
with open(ignore_file_path, 'r') as ignore_file:
for line in ignore_file.readlines():
self.ignore_items.extend(self._pattern(line.strip(' \n')))

def is_entry_ignored(self, relative_file):
def is_relative_file_ignored(cf_ignore_entry):
_logger.debug('is_relative_file_ignored - %s - %s', cf_ignore_entry, relative_file)
file_path = '/%s' % relative_file \
if cf_ignore_entry.startswith('/') and not relative_file.startswith('/') \
else relative_file
return fnmatch.fnmatch(file_path, cf_ignore_entry)

return any([is_relative_file_ignored(ignore_item)
for ignore_item in self.ignore_items])

@staticmethod
def _pattern(pattern):
if pattern.find('/') < 0:
return [pattern, os.path.join('**', pattern)]
elif pattern.endswith('/'):
return [os.path.join('/', pattern, '*'),
os.path.join('/', pattern, '**', '*'),
os.path.join('/', '**', pattern, '*'),
os.path.join('/', '**', pattern, '**', '*')]
else:
return [os.path.join('/', pattern), os.path.join('/', '**', pattern)]
25 changes: 2 additions & 23 deletions main/cloudfoundry_client/operations/push/push.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import fnmatch
import json
import logging
import os
Expand All @@ -7,33 +6,13 @@
import tempfile
import time

from cloudfoundry_client.operations.push.cf_ignore import CfIgnore
from cloudfoundry_client.operations.push.file_helper import FileHelper
from cloudfoundry_client.operations.push.validation.manifest import ManifestReader

_logger = logging.getLogger(__name__)


class _CfIgnore(object):
def __init__(self, application_path):
ignore_file_path = os.path.join(application_path, '.cfignore')
if os.path.isfile(ignore_file_path):
with open(ignore_file_path, 'r') as ignore_file:
self.ignore_items = [line.strip('\n ') for line in ignore_file.readlines()]
else:
self.ignore_items = []

def is_entry_ignored(self, relative_file):
def is_relative_file_ignored(cf_ignore_entry, file_path):
_logger.debug('is_relative_file_ignored - %s - %s', cf_ignore_entry, file_path)
return fnmatch.fnmatch('/%s' % file_path
if cf_ignore_entry.startswith('/') and not file_path.startswith('/')
else file_path,
cf_ignore_entry)

return any([is_relative_file_ignored(ignore_item, relative_file)
for ignore_item in self.ignore_items])


class PushOperation(object):
UPLOAD_TIMEOUT = 15 * 60

Expand Down Expand Up @@ -294,7 +273,7 @@ def generate_key(item):
@staticmethod
def _load_all_resources(top_directory):
application_items = {}
cf_ignore = _CfIgnore(top_directory)
cf_ignore = CfIgnore(top_directory)
for directory, file_names in FileHelper.walk(top_directory):
for file_name in file_names:
relative_file_location = os.path.join(directory, file_name)
Expand Down
6 changes: 4 additions & 2 deletions test/imported.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import sys

if sys.version_info.major == 2:
from mock import patch, call, MagicMock
from mock import patch, call, MagicMock, mock_open
from httplib import SEE_OTHER, CREATED, NO_CONTENT, ACCEPTED
def iterate_text(text):
for character in text:
yield character
built_in_entry = '__builtin__'

elif sys.version_info.major == 3:
from unittest.mock import patch, call, MagicMock
from unittest.mock import patch, call, MagicMock, mock_open
from http import HTTPStatus
SEE_OTHER = HTTPStatus.SEE_OTHER.value
CREATED = HTTPStatus.CREATED.value
Expand All @@ -17,5 +18,6 @@ def iterate_text(text):
def iterate_text(text):
for character in text:
yield bytes([character])
built_in_entry = 'builtins'
else:
raise ImportError('Invalid major version: %d' % sys.version_info.major)
52 changes: 52 additions & 0 deletions test/operations/push/test_cf_ignore.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import os
from unittest import TestCase

from cloudfoundry_client.operations.push.cf_ignore import CfIgnore
from imported import patch, mock_open, built_in_entry


class TestCfIgnore(TestCase):

def test_open_cfignore_file(self):
with patch("%s.open" % built_in_entry, mock_open(read_data="*.log")) as mock_file, \
patch('os.path.isfile', create=True) as mock_isfile:
mock_isfile.__return_value__ = True
application_path = '/some/path'
CfIgnore(application_path)

mock_file.assert_called_with(os.path.join(application_path, '.cfignore'), 'r')

def test_ignore_wildcard_resources(self):
with patch("%s.open" % built_in_entry, mock_open(read_data="*.log")), \
patch('os.path.isfile', create=True) as mock_isfile:
mock_isfile.__return_value__ = True
cf_ignore = CfIgnore('/some/path')

self.assertTrue(cf_ignore.is_entry_ignored("toto.log"))
self.assertTrue(cf_ignore.is_entry_ignored("/some/other/path/toto.log"))

def test_ignore_directory(self):
with patch("%s.open" % built_in_entry, mock_open(read_data="ignored/directory/")), \
patch('os.path.isfile', create=True) as mock_isfile:
mock_isfile.__return_value__ = True
cf_ignore = CfIgnore('/some/path')

self.assertTrue(cf_ignore.is_entry_ignored("ignored/directory/resource.file"))
self.assertTrue(cf_ignore.is_entry_ignored("/ignored/directory/resource.file"))
self.assertTrue(cf_ignore.is_entry_ignored("/some/sub/directory/containing/ignored/directory/resource.file"))
# File in fact
self.assertFalse(cf_ignore.is_entry_ignored('/ignored/directory'))

def test_ignore_file_with_directory(self):
with patch("%s.open" % built_in_entry, mock_open(read_data="ignored/directory/resource.file")), \
patch('os.path.isfile', create=True) as mock_isfile:
mock_isfile.__return_value__ = True
cf_ignore = CfIgnore('/some/path')

self.assertTrue(cf_ignore.is_entry_ignored("ignored/directory/resource.file"))
self.assertTrue(cf_ignore.is_entry_ignored("/ignored/directory/resource.file"))
self.assertTrue(cf_ignore.is_entry_ignored("/some/sub/directory/containing/ignored/directory/resource.file"))
# File in fact
self.assertFalse(cf_ignore.is_entry_ignored('ignored/resource.file'))


0 comments on commit fa479de

Please sign in to comment.