Skip to content
Merged

0.2.3 #162

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions gitfs/cache/gitignore.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ def __init__(self, ignore=False, submodules=False, path="."):
self.update()

def update(self):
self.items = ['/.git', '.git/*', '/.git/*', '*.keep']
self.items = ['.git', '.git/*', '/.git/*', '*.keep']

if self.ignore and os.path.exists(self.ignore):
with open(self.ignore) as gitignore:
new_items = filter(lambda line: line != "",
gitignore.read().split("\n"))

self.items += new_items
for item in gitignore.readlines():
item = item.strip()
if item and not item.startswith('#'):
self.items += item

if self.submodules and os.path.exists(self.submodules):
with open(self.submodules) as submodules:
Expand All @@ -67,7 +67,13 @@ def check_key(self, key):
return False

def _check_item_and_key(self, item, key):
if key.startswith("/"):
key = key[1:]

if item == key:
return True

if item.endswith("/") and key.startswith(item):
return True

return fnmatch.fnmatch(key, item)
8 changes: 6 additions & 2 deletions gitfs/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,9 @@ def diverge(self, upstream, branch):
def checkout(self, ref, *args, **kwargs):
result = self._repo.checkout(ref, *args, **kwargs)

# update ignore cache after a checkout
self.ignore.update()

status = self._repo.status()
for path, status in status.iteritems():
# path is in current status, move on
Expand All @@ -85,11 +88,12 @@ def checkout(self, ref, *args, **kwargs):

# check if file exists or not
if path not in self._repo.index:
os.unlink(self._full_path(path))
if path not in self.ignore:
os.unlink(self._full_path(path))
continue

# check files stats
stats = self.get_git_object_stat(path)
stats = self.get_git_object_default_stats(ref, path)
current_stat = os.lstat(self._full_path(path))

if stats['st_mode'] != current_stat.st_mode:
Expand Down
8 changes: 7 additions & 1 deletion gitfs/router.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,13 @@ def __call__(self, operation, *args):
view.__class__.__name__))
raise FuseOSError(ENOSYS)

return getattr(view, operation)(*args)
try:
return getattr(view, operation)(*args)
except FuseOSError as e:
raise e
except Exception as exception:
log.exception("A system call failed")
raise exception

def register(self, routes):
for regex, view in routes:
Expand Down
15 changes: 14 additions & 1 deletion gitfs/utils/args.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def __init__(self, parser):
("log", ("syslog", "string")),
("log_level", ("warning", "string")),
("cache_size", (800, "int")),
("sentry_dsn", (self.get_sentry_dsn, "string")),
])
self.config = self.build_config(parser.parse_args())

Expand Down Expand Up @@ -90,8 +91,17 @@ def check_args(self, args):
'%(message)s'.format(mount_point=args.mount_point)
handler.setFormatter(Formatter(fmt=logger_fmt))

if args.sentry_dsn != '':
from raven.conf import setup_logging
from raven.handlers.logging import SentryHandler

sentry_handler = SentryHandler(args.sentry_dsn)
sentry_handler.setLevel("ERROR")
setup_logging(sentry_handler)
log.addHandler(sentry_handler)

handler.setLevel(args.log_level.upper())
log.addHandler(handler)
log.setLevel(args.log_level.upper())

# set cache size
lru_cache.maxsize = args.cache_size
Expand Down Expand Up @@ -151,6 +161,9 @@ def get_repo_path(self, args):
def get_ssh_key(self, args):
return os.environ["HOME"] + "/.ssh/id_rsa"

def get_sentry_dsn(self, args):
return os.environ["SENTRY_DSN"] if "SENTRY_DSN" in os.environ else ""

def get_ssh_user(self, args):
url = args.remote_url
parse_result = urlparse(url)
Expand Down
5 changes: 3 additions & 2 deletions gitfs/worker/fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

Expand All @@ -21,7 +22,7 @@
class FetchWorker(Peasant):
name = 'FetchWorker'

def run(self):
def work(self):
while True:
fetch.wait(self.timeout)

Expand Down
8 changes: 8 additions & 0 deletions gitfs/worker/peasant.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,18 @@

from threading import Thread

from gitfs.log import log


class Peasant(Thread):
def __init__(self, *args, **kwargs):
super(Peasant, self).__init__()

for name, value in kwargs.iteritems():
setattr(self, name, value)

def run(self):
try:
self.work()
except:
log.exception("A worker is not feeling well")
16 changes: 10 additions & 6 deletions gitfs/worker/sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ def __init__(self, author_name, author_email, commiter_name,
self.strategy = strategy
self.commits = []

def run(self):
def work(self):
while True:
if shutting_down.is_set():
log.info("Stop sync worker")
Expand All @@ -67,12 +67,12 @@ def on_idle(self):
"""

if not syncing.is_set():
log.debug("Set syncing event (%d pending writes)", writers)
log.debug("Set syncing event (%d pending writes)", writers.value)
syncing.set()
else:
log.debug("Idling (%d pending writes)", writers)
log.debug("Idling (%d pending writes)", writers.value)

if writers == 0:
if writers.value == 0:
if self.commits:
log.info("Get some commits")
self.commit(self.commits)
Expand All @@ -97,8 +97,12 @@ def sync(self):

if self.repository.behind:
log.debug("I'm behind so I start merging")
self.merge()
need_to_push = True
try:
self.merge()
need_to_push = True
except:
log.exception("Merge failed")
return

if need_to_push:
try:
Expand Down
8 changes: 4 additions & 4 deletions tests/cache/test_gitignore.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ def test_init(self):
re=mocked_re):
gitignore = CachedIgnore("some_file", "some_file")

assert gitignore.items == ['/.git', '.git/*', '/.git/*', '*.keep',
'file', '/found/*', '/found',
'found']
assert gitignore.items == ['.git', '.git/*', '/.git/*',
'*.keep', 'file', '/found/*',
'/found', 'found']

def test_update(self):
gitignore = CachedIgnore()
Expand All @@ -47,5 +47,5 @@ def test_update(self):
def test_contains(self):
gitignore = CachedIgnore()

assert '/.git' in gitignore
assert '.git' in gitignore
assert 'file' not in gitignore
2 changes: 2 additions & 0 deletions tests/utils/test_args.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ def test_args(self):
mocked_file.mkdtemp.return_value = "/tmp"
mocked_pass.getuser.return_value = "test_user"
mocked_os.getgid.return_value = 1
mocked_os.environ = {}
mocked_os.path.abspath.return_value = "abs/tmp"
mocked_grp.getgrgid().gr_name = "test_group"
mocked_parser.parse_args.return_value = mocked_args
Expand All @@ -48,6 +49,7 @@ def test_args(self):
mocked_args.user = None
mocked_args.branch = None
mocked_args.ssh_user = None
mocked_args.sentry_dsn = ''

with patch.multiple('gitfs.utils.args', os=mocked_os, grp=mocked_grp,
getpass=mocked_pass, tempfile=mocked_file,
Expand Down
4 changes: 2 additions & 2 deletions tests/workers/test_fetch.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@


class TestFetchWorker(object):
def test_run(self):
def test_work(self):
mocked_peasant = MagicMock()
mocked_fetch = MagicMock(side_effect=ValueError)
mocked_fetch_event = MagicMock()
Expand All @@ -32,7 +32,7 @@ def test_run(self):
worker.timeout = 5

with pytest.raises(ValueError):
worker.run()
worker.work()

assert mocked_fetch.call_count == 1
mocked_fetch_event.wait.assert_called_once_with(5)
Expand Down
6 changes: 3 additions & 3 deletions tests/workers/test_sync.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@


class TestSyncWorker(object):
def test_run(self):
def test_work(self):
mocked_queue = MagicMock()
mocked_idle = MagicMock(side_effect=ValueError)

Expand All @@ -34,7 +34,7 @@ def test_run(self):
worker.timeout = 1

with pytest.raises(ValueError):
worker.run()
worker.work()

mocked_queue.get.assert_called_once_with(timeout=1, block=True)
assert mocked_idle.call_count == 1
Expand All @@ -47,7 +47,7 @@ def test_on_idle_with_commits_and_merges(self):
mocked_syncing.is_set.return_value = False

with patch.multiple("gitfs.worker.sync", syncing=mocked_syncing,
writers=0):
writers=MagicMock(value=0)):
worker = SyncWorker("name", "email", "name", "email",
strategy="strategy")
worker.commits = "commits"
Expand Down