Content-Length: 9652 | pFad | http://github.com/gitpython-developers/GitPython/pull/528.diff
thub.com
diff --git a/.gitignore b/.gitignore
index d35cddebd..a672c3f16 100644
--- a/.gitignore
+++ b/.gitignore
@@ -14,3 +14,4 @@ nbproject
.DS_Store
/*egg-info
/.tox
+.cache
diff --git a/.travis.yml b/.travis.yml
index 2d6764054..2691d87c4 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -29,7 +29,7 @@ install:
- cat git/test/fixtures/.gitconfig >> ~/.gitconfig
script:
# Make sure we limit open handles to see if we are leaking them
- - ulimit -n 110
+ - ulimit -n 128
- ulimit -n
- nosetests -v --with-coverage
- if [ "$TRAVIS_PYTHON_VERSION" == '3.4' ]; then flake8; fi
diff --git a/AUTHORS b/AUTHORS
index e2c3293cc..44ac4e2ff 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -15,5 +15,7 @@ Contributors are:
-Jonathan Chu
-Vincent Driessen
-Phil Elson
+-Daniele Esposti
+-Bernard `Guyzmo` Pratz
Portions derived from other open source works and are clearly marked.
diff --git a/git/remote.py b/git/remote.py
index d35e1fad1..e8cfe5161 100644
--- a/git/remote.py
+++ b/git/remote.py
@@ -33,6 +33,7 @@
from gitdb.util import join
from git.compat import (defenc, force_text, is_win)
import logging
+from git.exc import GitCommandError
log = logging.getLogger('git.remote')
@@ -494,12 +495,24 @@ def delete_url(self, url, **kwargs):
@property
def urls(self):
- """:return: Iterator yielding all configured URL targets on a remote
- as strings"""
- remote_details = self.repo.git.remote("show", self.name)
- for line in remote_details.split('\n'):
- if ' Push URL:' in line:
- yield line.split(': ')[-1]
+ """:return: Iterator yielding all configured URL targets on a remote as strings"""
+ try:
+ remote_details = self.repo.git.remote("get-url", "--all", self.name)
+ for line in remote_details.split('\n'):
+ yield line
+ except GitCommandError as ex:
+ ## We are on git < 2.7 (i.e TravisCI as of Oct-2016),
+ # so `get-utl` command does not exist yet!
+ # see: https://github.com/gitpython-developers/GitPython/pull/528#issuecomment-252976319
+ # and: http://stackoverflow.com/a/32991784/548792
+ #
+ if 'Unknown subcommand: get-url' in str(ex):
+ remote_details = self.repo.git.remote("show", self.name)
+ for line in remote_details.split('\n'):
+ if ' Push URL:' in line:
+ yield line.split(': ')[-1]
+ else:
+ raise ex
@property
def refs(self):
diff --git a/git/test/performance/lib.py b/git/test/performance/lib.py
index 0c4c20a47..b57b9b714 100644
--- a/git/test/performance/lib.py
+++ b/git/test/performance/lib.py
@@ -3,7 +3,6 @@
from git.test.lib import (
TestBase
)
-from gitdb.test.lib import skip_on_travis_ci
import tempfile
import logging
@@ -43,8 +42,6 @@ class TestBigRepoR(TestBase):
#} END invariants
def setUp(self):
- # This will raise on travis, which is what we want to happen early as to prevent us to do any work
- skip_on_travis_ci(lambda *args: None)(self)
try:
super(TestBigRepoR, self).setUp()
except AttributeError:
diff --git a/git/test/test_util.py b/git/test/test_util.py
index e07417b4b..6ba3d0d40 100644
--- a/git/test/test_util.py
+++ b/git/test/test_util.py
@@ -5,6 +5,7 @@
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import tempfile
+import gc
from git.test.lib import (
TestBase,
@@ -80,6 +81,7 @@ def test_lock_file(self):
# auto-release on destruction
del(other_lock_file)
+ gc.collect()
lock_file._obtain_lock_or_raise()
lock_file._release_lock()
diff --git a/git/util.py b/git/util.py
index c96a6b087..037fd91b5 100644
--- a/git/util.py
+++ b/git/util.py
@@ -48,6 +48,56 @@
#{ Utility Methods
+if platform.system() == 'Windows':
+ # This code is a derivative work of Portalocker http://code.activestate.com/recipes/65203/
+ import win32con
+ import win32file
+ import pywintypes
+
+ LOCK_EX = win32con.LOCKFILE_EXCLUSIVE_LOCK
+ LOCK_SH = 0 # the default
+ LOCK_NB = win32con.LOCKFILE_FAIL_IMMEDIATELY
+ LOCK_UN = 1 << 2
+
+ __overlapped = pywintypes.OVERLAPPED()
+
+ def flock(fd, flags=0):
+ hfile = win32file._get_osfhandle(fd)
+
+ if flags & LOCK_UN != 0:
+ # Unlock file descriptor
+ try:
+ win32file.UnlockFileEx(hfile, 0, -0x10000, __overlapped)
+ except pywintypes.error as exc_value:
+ # error: (158, 'UnlockFileEx', 'The segment is already unlocked.')
+ # To match the 'posix' implementation, silently ignore this error
+ if exc_value[0] == 158:
+ pass
+ else:
+ # Q: Are there exceptions/codes we should be dealing with here?
+ raise
+
+ elif flags & LOCK_EX != 0:
+ # Lock file
+ try:
+ win32file.LockFileEx(hfile, flags, 0, -0x10000, __overlapped)
+ except pywintypes.error as exc_value:
+ if exc_value[0] == 33:
+ # error: (33, 'LockFileEx',
+ # 'The process cannot access the file because another process has locked
+ # a portion of the file.')
+ raise IOError(33, exc_value[2])
+ else:
+ # Q: Are there exceptions/codes we should be dealing with here?
+ raise
+
+ else:
+ raise NotImplementedError("Unsupported set of bitflags {}".format(bin(flags)))
+
+
+else:
+ from fcntl import flock, LOCK_UN, LOCK_EX, LOCK_NB
+
def unbare_repo(func):
"""Methods with this decorator raise InvalidGitRepositoryError if they
@@ -555,9 +605,10 @@ class LockFile(object):
As we are a utility class to be derived from, we only use protected methods.
Locks will automatically be released on destruction"""
- __slots__ = ("_file_path", "_owns_lock")
+ __slots__ = ("_file_path", "_owns_lock", "_file_descriptor")
def __init__(self, file_path):
+ self._file_descriptor = None
self._file_path = file_path
self._owns_lock = False
@@ -579,20 +630,21 @@ def _obtain_lock_or_raise(self):
:raise IOError: if a lock was already present or a lock file could not be written"""
if self._has_lock():
return
+
lock_file = self._lock_file_path()
- if os.path.isfile(lock_file):
- raise IOError("Lock for file %r did already exist, delete %r in case the lock is illegal" %
- (self._file_path, lock_file))
+ # Create file and lock
try:
- flags = os.O_WRONLY | os.O_CREAT | os.O_EXCL
+ flags = os.O_CREAT
if is_win:
flags |= os.O_SHORT_LIVED
fd = os.open(lock_file, flags, 0)
- os.close(fd)
except OSError as e:
raise IOError(str(e))
+ flock(fd, LOCK_EX | LOCK_NB)
+
+ self._file_descriptor = fd
self._owns_lock = True
def _obtain_lock(self):
@@ -605,14 +657,21 @@ def _release_lock(self):
if not self._has_lock():
return
+ fd = self._file_descriptor
+ lock_file = self._lock_file_path()
+
+ flock(fd, LOCK_UN)
+ os.close(fd)
+
# if someone removed our file beforhand, lets just flag this issue
# instead of failing, to make it more usable.
- lfp = self._lock_file_path()
try:
- rmfile(lfp)
+ rmfile(lock_file)
except OSError:
pass
+
self._owns_lock = False
+ self._file_descriptor = None
class BlockingLockFile(LockFile):
@@ -647,7 +706,7 @@ def _obtain_lock(self):
try:
super(BlockingLockFile, self)._obtain_lock()
except IOError:
- # synity check: if the directory leading to the lockfile is not
+ # sanity check: if the directory leading to the lockfile is not
# readable anymore, raise an execption
curtime = time.time()
if not os.path.isdir(os.path.dirname(self._lock_file_path())):
diff --git a/setup.py b/setup.py
index c7dd25fcc..43b0505bd 100755
--- a/setup.py
+++ b/setup.py
@@ -13,6 +13,7 @@
import logging
import os
import sys
+import platform
from os import path
with open(path.join(path.dirname(__file__), 'VERSION')) as v:
@@ -21,6 +22,10 @@
with open('requirements.txt') as reqs_file:
requirements = reqs_file.read().splitlines()
+if platform.system() == 'Windows':
+ with open('win32-requirements.txt') as reqs_file:
+ requirements += reqs_file.read().splitlines()
+
class build_py(_build_py):
@@ -65,6 +70,8 @@ def _stamp_version(filename):
print("WARNING: Couldn't find version line in file %s" % filename, file=sys.stderr)
install_requires = ['gitdb >= 0.6.4']
+if platform.system() == 'Windows':
+ install_requires.append("pypiwin32 >= 219")
extras_require = {
':python_version == "2.6"': ['ordereddict'],
}
diff --git a/win32-requirements.txt b/win32-requirements.txt
new file mode 100644
index 000000000..0008dcffd
--- /dev/null
+++ b/win32-requirements.txt
@@ -0,0 +1,2 @@
+-r requirements.txt
+pypiwin32 >= 219
--- a PPN by Garber Painting Akron. With Image Size Reduction included!Fetched URL: http://github.com/gitpython-developers/GitPython/pull/528.diff
Alternative Proxies:
Alternative Proxy
pFad Proxy
pFad v3 Proxy
pFad v4 Proxy