Skip to content

Commit

Permalink
cygwin, gitpython-developers#525: Allow '/cygdrive/c/' paths on repo …
Browse files Browse the repository at this point in the history
…init

- Cygwin TCs failing:
  - PY2: err: 13, fail: 2
  - PY3: err: 12, fail: 2
  • Loading branch information
ankostis committed Oct 14, 2016
1 parent b2749b1 commit 5179f87
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 29 deletions.
7 changes: 6 additions & 1 deletion git/repo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from git.objects import Submodule, RootModule, Commit
from git.refs import HEAD, Head, Reference, TagReference
from git.remote import Remote, add_progress, to_progress_instance
from git.util import Actor, finalize_process
from git.util import Actor, finalize_process, decygpath

from .fun import rev_parse, is_git_dir, find_git_dir, touch

Expand Down Expand Up @@ -99,6 +99,8 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
repo = Repo("~/Development/git-python.git")
repo = Repo("$REPOSITORIES/Development/git-python.git")
In *Cygwin*, path may be a `'cygdrive/...'` prefixed path.
:param odbt:
Object DataBase type - a type which is constructed by providing
the directory containing the database objects, i.e. .git/objects. It will
Expand All @@ -111,6 +113,9 @@ def __init__(self, path=None, odbt=DefaultDBType, search_parent_directories=Fals
:raise InvalidGitRepositoryError:
:raise NoSuchPathError:
:return: git.Repo """
if path and Git.is_cygwin():
path = decygpath(path)

epath = _expand_path(path or os.getcwd())
self.git = None # should be set for __del__ not to fail in case we raise
if not os.path.exists(epath):
Expand Down
4 changes: 3 additions & 1 deletion git/test/test_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@
assert_true,
raises
)
from git.util import HIDE_WINDOWS_KNOWN_ERRORS
from git.util import HIDE_WINDOWS_KNOWN_ERRORS, cygpath
from git.test.lib import with_rw_directory
from git.util import join_path_native, rmtree, rmfile
from gitdb.util import bin_to_hex
Expand Down Expand Up @@ -913,6 +913,8 @@ def test_work_tree_unsupported(self, rw_dir):
rw_master = self.rorepo.clone(join_path_native(rw_dir, 'master_repo'))
rw_master.git.checkout('HEAD~10')
worktree_path = join_path_native(rw_dir, 'worktree_repo')
if Git.is_cygwin():
worktree_path = cygpath(worktree_path)
try:
rw_master.git.worktree('add', worktree_path, 'master')
except Exception as ex:
Expand Down
79 changes: 53 additions & 26 deletions git/test/test_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,34 @@
Actor,
IterableList,
cygpath,
decygpath
)


_norm_cygpath_pairs = (
(r'foo\bar', 'foo/bar'),
(r'foo/bar', 'foo/bar'),

(r'C:\Users', '/cygdrive/c/Users'),
(r'C:\d/e', '/cygdrive/c/d/e'),

('C:\\', '/cygdrive/c/'),

(r'\\server\C$\Users', '//server/C$/Users'),
(r'\\server\C$', '//server/C$'),
('\\\\server\\c$\\', '//server/c$/'),
(r'\\server\BAR/', '//server/BAR/'),

(r'D:/Apps', '/cygdrive/d/Apps'),
(r'D:/Apps\fOO', '/cygdrive/d/Apps/fOO'),
(r'D:\Apps/123', '/cygdrive/d/Apps/123'),
)

_unc_cygpath_pairs = (
(r'\\?\a:\com', '/cygdrive/a/com'),
(r'\\?\a:/com', '/cygdrive/a/com'),

(r'\\?\UNC\server\D$\Apps', '//server/D$/Apps'),
)


Expand All @@ -54,46 +82,45 @@ def setup(self):
"array": [42],
}

@skipIf(not is_win, "Paths specifically for Windows.")
@ddt.idata(_norm_cygpath_pairs + _unc_cygpath_pairs)
def test_cygpath_ok(self, case):
wpath, cpath = case
cwpath = cygpath(wpath)
self.assertEqual(cwpath, cpath, wpath)

@skipIf(not is_win, "Paths specifically for Windows.")
@ddt.data(
(r'foo\bar', 'foo/bar'),
(r'foo/bar', 'foo/bar'),
(r'./bar', 'bar'),
(r'.\bar', 'bar'),
(r'../bar', '../bar'),
(r'..\bar', '../bar'),
(r'../bar/.\foo/../chu', '../bar/chu'),
(r'C:\Users', '/cygdrive/c/Users'),
(r'C:\d/e', '/cygdrive/c/d/e'),
(r'\\?\a:\com', '/cygdrive/a/com'),
(r'\\?\a:/com', '/cygdrive/a/com'),
(r'\\server\C$\Users', '//server/C$/Users'),
(r'\\server\C$', '//server/C$'),
(r'\\server\BAR/', '//server/BAR/'),
(r'\\?\UNC\server\D$\Apps', '//server/D$/Apps'),
(r'D:/Apps', '/cygdrive/d/Apps'),
(r'D:/Apps\fOO', '/cygdrive/d/Apps/fOO'),
(r'D:\Apps/123', '/cygdrive/d/Apps/123'),
)
def test_cygpath_ok(self, case):
def test_cygpath_norm_ok(self, case):
wpath, cpath = case
self.assertEqual(cygpath(wpath), cpath or wpath)
cwpath = cygpath(wpath)
self.assertEqual(cwpath, cpath or wpath, wpath)

@skipIf(not is_win, "Paths specifically for Windows.")
@ddt.data(
(r'C:Relative', None),
(r'D:Apps\123', None),
(r'D:Apps/123', None),
(r'\\?\a:rel', None),
(r'\\share\a:rel', None),
r'C:',
r'C:Relative',
r'D:Apps\123',
r'D:Apps/123',
r'\\?\a:rel',
r'\\share\a:rel',
)
def test_cygpath_invalids(self, case):
def test_cygpath_invalids(self, wpath):
cwpath = cygpath(wpath)
self.assertEqual(cwpath, wpath.replace('\\', '/'), wpath)

@skipIf(not is_win, "Paths specifically for Windows.")
@ddt.idata(_norm_cygpath_pairs)
def test_decygpath(self, case):
wpath, cpath = case
self.assertEqual(cygpath(wpath), cpath or wpath.replace('\\', '/'))
wcpath = decygpath(cpath)
self.assertEqual(wcpath, wpath.replace('/', '\\'), cpath)

def test_it_should_dashify(self):
assert_equal('this-is-my-argument', dashify('this_is_my_argument'))
Expand Down
14 changes: 13 additions & 1 deletion git/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ def _cygexpath(drive, path):
# It's an error, leave it alone just slashes)
p = path
else:
p = osp.normpath(osp.expandvars(os.path.expanduser(path)))
p = path and osp.normpath(osp.expandvars(os.path.expanduser(path)))
if osp.isabs(p):
if drive:
# Confusing, maybe a remote system should expand vars.
Expand Down Expand Up @@ -278,6 +278,18 @@ def cygpath(path):
return path


_decygpath_regex = re.compile(r"/cygdrive/(\w)(/.*)?")


def decygpath(path):
m = _decygpath_regex.match(path)
if m:
drive, rest_path = m.groups()
path = '%s:%s' % (drive.upper(), rest_path or '')

return path.replace('/', '\\')


#: Store boolean flags denoting if a specific Git executable
#: is from a Cygwin installation (since `cache_lru()` unsupported on PY2).
_is_cygwin_cache = {}
Expand Down

0 comments on commit 5179f87

Please sign in to comment.