Skip to content

Commit 0181a40

Browse files
authored
Merge pull request gitpython-developers#555 from ankostis/cntxtmman
Retrofit `repo` class as context-man to cleanup global mman on repo-delete
2 parents 88732b6 + f858c44 commit 0181a40

File tree

4 files changed

+45
-23
lines changed

4 files changed

+45
-23
lines changed

git/__init__.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ def _init_externals():
4949
LockFile,
5050
BlockingLockFile,
5151
Stats,
52-
Actor
52+
Actor,
53+
rmtree,
5354
)
5455

5556
#} END imports

git/cmd.py

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -823,27 +823,30 @@ def _call_process(self, method, *args, **kwargs):
823823
is realized as non-existent
824824
825825
:param kwargs:
826-
is a dict of keyword arguments.
827-
This function accepts the same optional keyword arguments
828-
as execute().
829-
830-
``Examples``::
826+
It contains key-values for the following:
827+
- the :meth:`execute()` kwds, as listed in :var:`execute_kwargs`;
828+
- "command options" to be converted by :meth:`transform_kwargs()`;
829+
- the `'insert_kwargs_after'` key which its value must match one of ``*args``,
830+
and any cmd-options will be appended after the matched arg.
831+
832+
Examples::
833+
831834
git.rev_list('master', max_count=10, header=True)
835+
836+
turns into::
837+
838+
git rev-list max-count 10 --header master
832839
833840
:return: Same as ``execute``"""
834841
# Handle optional arguments prior to calling transform_kwargs
835842
# otherwise these'll end up in args, which is bad.
836-
_kwargs = dict()
837-
for kwarg in execute_kwargs:
838-
try:
839-
_kwargs[kwarg] = kwargs.pop(kwarg)
840-
except KeyError:
841-
pass
843+
exec_kwargs = dict((k, v) for k, v in kwargs.items() if k in execute_kwargs)
844+
opts_kwargs = dict((k, v) for k, v in kwargs.items() if k not in execute_kwargs)
842845

843-
insert_after_this_arg = kwargs.pop('insert_kwargs_after', None)
846+
insert_after_this_arg = opts_kwargs.pop('insert_kwargs_after', None)
844847

845848
# Prepare the argument list
846-
opt_args = self.transform_kwargs(**kwargs)
849+
opt_args = self.transform_kwargs(**opts_kwargs)
847850
ext_args = self.__unpack_args([a for a in args if a is not None])
848851

849852
if insert_after_this_arg is None:
@@ -852,11 +855,11 @@ def _call_process(self, method, *args, **kwargs):
852855
try:
853856
index = ext_args.index(insert_after_this_arg)
854857
except ValueError:
855-
raise ValueError("Couldn't find argument '%s' in args %s to insert kwargs after"
858+
raise ValueError("Couldn't find argument '%s' in args %s to insert cmd options after"
856859
% (insert_after_this_arg, str(ext_args)))
857860
# end handle error
858861
args = ext_args[:index + 1] + opt_args + ext_args[index + 1:]
859-
# end handle kwargs
862+
# end handle opts_kwargs
860863

861864
call = [self.GIT_PYTHON_GIT_EXECUTABLE]
862865

@@ -871,7 +874,7 @@ def _call_process(self, method, *args, **kwargs):
871874
call.append(dashify(method))
872875
call.extend(args)
873876

874-
return self.execute(call, **_kwargs)
877+
return self.execute(call, **exec_kwargs)
875878

876879
def _parse_object_header(self, header_line):
877880
"""

git/repo/base.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@
3333
import os.path as osp
3434

3535
from .fun import rev_parse, is_git_dir, find_submodule_git_dir, touch
36+
import gc
37+
import gitdb
3638

3739

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

182+
def __enter__(self):
183+
return self
184+
185+
def __exit__(self, exc_type, exc_value, traceback):
186+
self.close()
187+
180188
def __del__(self):
189+
self.close()
190+
191+
def close(self):
181192
if self.git:
182193
self.git.clear_cache()
194+
gc.collect()
195+
gitdb.util.mman.collect()
196+
gc.collect()
183197

184198
def __eq__(self, rhs):
185199
if isinstance(rhs, Repo):

git/test/lib/helper.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,22 @@
77

88
import contextlib
99
from functools import wraps
10-
import sys
10+
import gc
1111
import io
1212
import logging
1313
import os
14+
import sys
1415
import tempfile
1516
import textwrap
1617
import time
1718

1819
from git.compat import string_types, is_win
1920
from git.util import rmtree, cwd
21+
import gitdb
2022

2123
import os.path as osp
24+
25+
2226
if sys.version_info[0:2] == (2, 6):
2327
import unittest2 as unittest
2428
else:
@@ -96,7 +100,6 @@ def wrapper(self):
96100
# a windows-only issue. In fact things should be deleted, as well as
97101
# memory maps closed, once objects go out of scope. For some reason
98102
# though this is not the case here unless we collect explicitly.
99-
import gc
100103
gc.collect()
101104
if not keep:
102105
rmtree(path)
@@ -144,9 +147,10 @@ def repo_creator(self):
144147
os.chdir(prev_cwd)
145148
rw_repo.git.clear_cache()
146149
rw_repo = None
147-
import gc
148-
gc.collect()
149150
if repo_dir is not None:
151+
gc.collect()
152+
gitdb.util.mman.collect()
153+
gc.collect()
150154
rmtree(repo_dir)
151155
# END rm test repo if possible
152156
# END cleanup
@@ -303,7 +307,8 @@ def remote_repo_creator(self):
303307
rw_daemon_repo.git.clear_cache()
304308
del rw_repo
305309
del rw_daemon_repo
306-
import gc
310+
gc.collect()
311+
gitdb.util.mman.collect()
307312
gc.collect()
308313
if rw_repo_dir:
309314
rmtree(rw_repo_dir)
@@ -357,7 +362,6 @@ def setUpClass(cls):
357362
each test type has its own repository
358363
"""
359364
from git import Repo
360-
import gc
361365
gc.collect()
362366
cls.rorepo = Repo(GIT_REPO)
363367

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy