Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrofit repo class as context-man to cleanup global mman on repo-delete #555

Merged
merged 4 commits into from
Feb 25, 2017
Merged
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
3 changes: 2 additions & 1 deletion git/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ def _init_externals():
LockFile,
BlockingLockFile,
Stats,
Actor
Actor,
rmtree,
)

#} END imports
Expand Down
35 changes: 19 additions & 16 deletions git/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -822,27 +822,30 @@ def _call_process(self, method, *args, **kwargs):
is realized as non-existent

:param kwargs:
is a dict of keyword arguments.
This function accepts the same optional keyword arguments
as execute().

``Examples``::
It contains key-values for the following:
- the :meth:`execute()` kwds, as listed in :var:`execute_kwargs`;
- "command options" to be converted by :meth:`transform_kwargs()`;
- the `'insert_kwargs_after'` key which its value must match one of ``*args``,
and any cmd-options will be appended after the matched arg.

Examples::

git.rev_list('master', max_count=10, header=True)

turns into::

git rev-list max-count 10 --header master

:return: Same as ``execute``"""
# Handle optional arguments prior to calling transform_kwargs
# otherwise these'll end up in args, which is bad.
_kwargs = dict()
for kwarg in execute_kwargs:
try:
_kwargs[kwarg] = kwargs.pop(kwarg)
except KeyError:
pass
exec_kwargs = dict((k, v) for k, v in kwargs.items() if k in execute_kwargs)
opts_kwargs = dict((k, v) for k, v in kwargs.items() if k not in execute_kwargs)

insert_after_this_arg = kwargs.pop('insert_kwargs_after', None)
insert_after_this_arg = opts_kwargs.pop('insert_kwargs_after', None)

# Prepare the argument list
opt_args = self.transform_kwargs(**kwargs)
opt_args = self.transform_kwargs(**opts_kwargs)
ext_args = self.__unpack_args([a for a in args if a is not None])

if insert_after_this_arg is None:
Expand All @@ -851,11 +854,11 @@ def _call_process(self, method, *args, **kwargs):
try:
index = ext_args.index(insert_after_this_arg)
except ValueError:
raise ValueError("Couldn't find argument '%s' in args %s to insert kwargs after"
raise ValueError("Couldn't find argument '%s' in args %s to insert cmd options after"
% (insert_after_this_arg, str(ext_args)))
# end handle error
args = ext_args[:index + 1] + opt_args + ext_args[index + 1:]
# end handle kwargs
# end handle opts_kwargs

call = [self.GIT_PYTHON_GIT_EXECUTABLE]

Expand All @@ -870,7 +873,7 @@ def _call_process(self, method, *args, **kwargs):
call.append(dashify(method))
call.extend(args)

return self.execute(call, **_kwargs)
return self.execute(call, **exec_kwargs)

def _parse_object_header(self, header_line):
"""
Expand Down
14 changes: 14 additions & 0 deletions git/repo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
import os.path as osp

from .fun import rev_parse, is_git_dir, find_submodule_git_dir, touch
import gc
import gitdb


log = logging.getLogger(__name__)
Expand Down Expand Up @@ -177,9 +179,21 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
args.append(self.git)
self.odb = odbt(*args)

def __enter__(self):
return self

def __exit__(self, exc_type, exc_value, traceback):
self.close()

def __del__(self):
self.close()

def close(self):
if self.git:
self.git.clear_cache()
gc.collect()
gitdb.util.mman.collect()
gc.collect()

def __eq__(self, rhs):
if isinstance(rhs, Repo):
Expand Down
16 changes: 10 additions & 6 deletions git/test/lib/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,22 @@

import contextlib
from functools import wraps
import sys
import gc
import io
import logging
import os
import sys
import tempfile
import textwrap
import time

from git.compat import string_types, is_win
from git.util import rmtree, cwd
import gitdb

import os.path as osp


if sys.version_info[0:2] == (2, 6):
import unittest2 as unittest
else:
Expand Down Expand Up @@ -96,7 +100,6 @@ def wrapper(self):
# a windows-only issue. In fact things should be deleted, as well as
# memory maps closed, once objects go out of scope. For some reason
# though this is not the case here unless we collect explicitly.
import gc
gc.collect()
if not keep:
rmtree(path)
Expand Down Expand Up @@ -144,9 +147,10 @@ def repo_creator(self):
os.chdir(prev_cwd)
rw_repo.git.clear_cache()
rw_repo = None
import gc
gc.collect()
if repo_dir is not None:
gc.collect()
gitdb.util.mman.collect()
gc.collect()
rmtree(repo_dir)
# END rm test repo if possible
# END cleanup
Expand Down Expand Up @@ -303,7 +307,8 @@ def remote_repo_creator(self):
rw_daemon_repo.git.clear_cache()
del rw_repo
del rw_daemon_repo
import gc
gc.collect()
gitdb.util.mman.collect()
gc.collect()
if rw_repo_dir:
rmtree(rw_repo_dir)
Expand Down Expand Up @@ -357,7 +362,6 @@ def setUpClass(cls):
each test type has its own repository
"""
from git import Repo
import gc
gc.collect()
cls.rorepo = Repo(GIT_REPO)

Expand Down