Skip to content

Commit e6e23ed

Browse files
committed
cygwin, #533: Try to make it work with Cygwin's Git.
+ Make `Git.polish_url()` convert paths into Cygwin-friendly paths. + Add utility and soe TCs for funcs for detecting cygwin and converting abs-paths to `/cygdrive/c/...`. - Cygwin TCs failing: - PY2: err: 14, fail: 3 - PY3: err: 13, fail: 3
1 parent ba7c2a0 commit e6e23ed

File tree

5 files changed

+250
-67
lines changed

5 files changed

+250
-67
lines changed

git/cmd.py

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
)
3232
from git.exc import CommandError
3333
from git.odict import OrderedDict
34+
from git.util import is_cygwin_git, cygpath
3435

3536
from .exc import (
3637
GitCommandError,
@@ -190,9 +191,24 @@ def __setstate__(self, d):
190191
# Override this value using `Git.USE_SHELL = True`
191192
USE_SHELL = False
192193

194+
@classmethod
195+
def is_cygwin(cls):
196+
return is_cygwin_git(cls.GIT_PYTHON_GIT_EXECUTABLE)
197+
193198
@classmethod
194199
def polish_url(cls, url):
195-
return url.replace("\\\\", "\\").replace("\\", "/")
200+
if cls.is_cygwin():
201+
"""Remove any backslahes from urls to be written in config files.
202+
203+
Windows might create config-files containing paths with backslashed,
204+
but git stops liking them as it will escape the backslashes.
205+
Hence we undo the escaping just to be sure.
206+
"""
207+
url = cygpath(url)
208+
else:
209+
url = url.replace("\\\\", "\\").replace("\\", "/")
210+
211+
return url
196212

197213
class AutoInterrupt(object):
198214
"""Kill/Interrupt the stored process instance once this instance goes out of scope. It is

git/repo/base.py

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -4,51 +4,21 @@
44
# This module is part of GitPython and is released under
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

7-
from git.exc import (
8-
InvalidGitRepositoryError,
9-
NoSuchPathError,
10-
GitCommandError
11-
)
12-
from git.cmd import (
13-
Git,
14-
handle_process_output
15-
)
16-
from git.refs import (
17-
HEAD,
18-
Head,
19-
Reference,
20-
TagReference,
21-
)
22-
from git.objects import (
23-
Submodule,
24-
RootModule,
25-
Commit
26-
)
27-
from git.util import (
28-
Actor,
29-
finalize_process
30-
)
31-
from git.index import IndexFile
32-
from git.config import GitConfigParser
33-
from git.remote import (
34-
Remote,
35-
add_progress,
36-
to_progress_instance
37-
)
38-
39-
from git.db import GitCmdObjectDB
7+
from collections import namedtuple
8+
import logging
9+
import os
10+
import re
11+
import sys
4012

4113
from gitdb.util import (
4214
join,
4315
isfile,
4416
hex_to_bin
4517
)
4618

47-
from .fun import (
48-
rev_parse,
49-
is_git_dir,
50-
find_git_dir,
51-
touch,
19+
from git.cmd import (
20+
Git,
21+
handle_process_output
5222
)
5323
from git.compat import (
5424
text_type,
@@ -58,12 +28,17 @@
5828
range,
5929
is_win,
6030
)
31+
from git.config import GitConfigParser
32+
from git.db import GitCmdObjectDB
33+
from git.exc import InvalidGitRepositoryError, NoSuchPathError, GitCommandError
34+
from git.index import IndexFile
35+
from git.objects import Submodule, RootModule, Commit
36+
from git.refs import HEAD, Head, Reference, TagReference
37+
from git.remote import Remote, add_progress, to_progress_instance
38+
from git.util import Actor, finalize_process
39+
40+
from .fun import rev_parse, is_git_dir, find_git_dir, touch
6141

62-
import os
63-
import sys
64-
import re
65-
import logging
66-
from collections import namedtuple
6742

6843
log = logging.getLogger(__name__)
6944

@@ -875,12 +850,22 @@ def _clone(cls, git, url, path, odb_default_type, progress, **kwargs):
875850
progress = to_progress_instance(progress)
876851

877852
odbt = kwargs.pop('odbt', odb_default_type)
878-
proc = git.clone(url, path, with_extended_output=True, as_process=True,
853+
854+
## A bug win cygwin's Git, when `--bare`
855+
# it prepends the basename of the `url` into the `path::
856+
# git clone --bare /cygwin/a/foo.git C:\\Work
857+
# becomes::
858+
# git clone --bare /cygwin/a/foo.git /cygwin/a/C:\\Work
859+
#
860+
clone_path = (Git.polish_url(path)
861+
if Git.is_cygwin() and 'bare' in kwargs
862+
else path)
863+
proc = git.clone(Git.polish_url(url), clone_path, with_extended_output=True, as_process=True,
879864
v=True, **add_progress(kwargs, git, progress))
880865
if progress:
881866
handle_process_output(proc, None, progress.new_message_handler(), finalize_process)
882867
else:
883-
(stdout, stderr) = proc.communicate() # FIXME: Will block of outputs are big!
868+
(stdout, stderr) = proc.communicate() # FIXME: Will block if outputs are big!
884869
log.debug("Cmd(%s)'s unused stdout: %s", getattr(proc, 'args', ''), stdout)
885870
finalize_process(proc, stderr=stderr)
886871

git/test/lib/helper.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
'GIT_REPO', 'GIT_DAEMON_PORT'
3333
)
3434

35-
log = logging.getLogger('git.util')
35+
log = logging.getLogger(__name__)
3636

3737
#{ Routines
3838

git/test/test_util.py

Lines changed: 55 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,19 @@
55
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
66

77
import tempfile
8+
import time
9+
from unittest.case import skipIf
10+
11+
import ddt
812

13+
from git.cmd import dashify
14+
from git.compat import string_types, is_win
15+
from git.objects.util import (
16+
altz_to_utctz_str,
17+
utctz_to_altz,
18+
verify_utctz,
19+
parse_date,
20+
)
921
from git.test.lib import (
1022
TestBase,
1123
assert_equal
@@ -15,19 +27,9 @@
1527
BlockingLockFile,
1628
get_user_id,
1729
Actor,
18-
IterableList
30+
IterableList,
31+
cygpath,
1932
)
20-
from git.objects.util import (
21-
altz_to_utctz_str,
22-
utctz_to_altz,
23-
verify_utctz,
24-
parse_date,
25-
)
26-
from git.cmd import dashify
27-
from git.compat import string_types, is_win
28-
29-
import time
30-
import ddt
3133

3234

3335
class TestIterableMember(object):
@@ -52,6 +54,47 @@ def setup(self):
5254
"array": [42],
5355
}
5456

57+
@skipIf(not is_win, "Paths specifically for Windows.")
58+
@ddt.data(
59+
(r'foo\bar', 'foo/bar'),
60+
(r'foo/bar', 'foo/bar'),
61+
(r'./bar', 'bar'),
62+
(r'.\bar', 'bar'),
63+
(r'../bar', '../bar'),
64+
(r'..\bar', '../bar'),
65+
(r'../bar/.\foo/../chu', '../bar/chu'),
66+
67+
(r'C:\Users', '/cygdrive/c/Users'),
68+
(r'C:\d/e', '/cygdrive/c/d/e'),
69+
70+
(r'\\?\a:\com', '/cygdrive/a/com'),
71+
(r'\\?\a:/com', '/cygdrive/a/com'),
72+
73+
(r'\\server\C$\Users', '//server/C$/Users'),
74+
(r'\\server\C$', '//server/C$'),
75+
(r'\\server\BAR/', '//server/BAR/'),
76+
(r'\\?\UNC\server\D$\Apps', '//server/D$/Apps'),
77+
78+
(r'D:/Apps', '/cygdrive/d/Apps'),
79+
(r'D:/Apps\fOO', '/cygdrive/d/Apps/fOO'),
80+
(r'D:\Apps/123', '/cygdrive/d/Apps/123'),
81+
)
82+
def test_cygpath_ok(self, case):
83+
wpath, cpath = case
84+
self.assertEqual(cygpath(wpath), cpath or wpath)
85+
86+
@skipIf(not is_win, "Paths specifically for Windows.")
87+
@ddt.data(
88+
(r'C:Relative', None),
89+
(r'D:Apps\123', None),
90+
(r'D:Apps/123', None),
91+
(r'\\?\a:rel', None),
92+
(r'\\share\a:rel', None),
93+
)
94+
def test_cygpath_invalids(self, case):
95+
wpath, cpath = case
96+
self.assertEqual(cygpath(wpath), cpath or wpath.replace('\\', '/'))
97+
5598
def test_it_should_dashify(self):
5699
assert_equal('this-is-my-argument', dashify('this_is_my_argument'))
57100
assert_equal('foo', dashify('foo'))

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