From ce344df30c59673bc7356efe64ec540c0719a201 Mon Sep 17 00:00:00 2001 From: Kostis Anagnostopoulos Date: Tue, 4 Oct 2016 14:29:28 +0200 Subject: [PATCH] MINGW, #525: FIX remote urls in config-files + Parse all config-urls \-->/. + Used relative daemon-paths. + Use git-daemon PORT above 10k; on Windows all below need Admin rights. +FIXED git-daemon @with_rw_and_rw_remote_repo(): + test_base.test_with_rw_remote_and_rw_repo() PASS. + test_remote.test_base() now freezes! (so still hidden win_err) + repo_test: minor finally delete test-repos created inside this repo. --- git/cmd.py | 6 ++- git/remote.py | 4 +- git/repo/base.py | 2 +- git/test/lib/helper.py | 89 +++++++++++++++++++++++--------------- git/test/test_base.py | 11 ----- git/test/test_docs.py | 2 +- git/test/test_remote.py | 9 ++-- git/test/test_repo.py | 13 ++++-- git/test/test_submodule.py | 2 +- 9 files changed, 77 insertions(+), 61 deletions(-) diff --git a/git/cmd.py b/git/cmd.py index b1c18998c..cf3ba5edd 100644 --- a/git/cmd.py +++ b/git/cmd.py @@ -181,14 +181,18 @@ def __setstate__(self, d): # Override this value using `Git.USE_SHELL = True` USE_SHELL = False - class AutoInterrupt(object): + @classmethod + def polish_url(cls, url): + return url.replace("\\\\", "\\").replace("\\", "/") + class AutoInterrupt(object): """Kill/Interrupt the stored process instance once this instance goes out of scope. It is used to prevent processes piling up in case iterators stop reading. Besides all attributes are wired through to the contained process object. The wait method was overridden to perform automatic status code checking and possibly raise.""" + __slots__ = ("proc", "args") def __init__(self, proc, args): diff --git a/git/remote.py b/git/remote.py index a7d3fe7e9..8a46b2c56 100644 --- a/git/remote.py +++ b/git/remote.py @@ -29,7 +29,7 @@ join_path, finalize_process ) -from git.cmd import handle_process_output +from git.cmd import handle_process_output, Git from gitdb.util import join from git.compat import (defenc, force_text, is_win) import logging @@ -570,7 +570,7 @@ def create(cls, repo, name, url, **kwargs): :raise GitCommandError: in case an origin with that name already exists""" scmd = 'add' kwargs['insert_kwargs_after'] = scmd - repo.git.remote(scmd, name, url, **kwargs) + repo.git.remote(scmd, name, Git.polish_url(url), **kwargs) return cls(repo, name) # add is an alias diff --git a/git/repo/base.py b/git/repo/base.py index 4e9549eea..c5cdce7c6 100644 --- a/git/repo/base.py +++ b/git/repo/base.py @@ -897,7 +897,7 @@ def _clone(cls, git, url, path, odb_default_type, progress, **kwargs): repo = cls(path, odbt=odbt) if repo.remotes: with repo.remotes[0].config_writer as writer: - writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/")) + writer.set_value('url', Git.polish_url(repo.remotes[0].url)) # END handle remote repo return repo diff --git a/git/test/lib/helper.py b/git/test/lib/helper.py index 092068b9f..8f86599f9 100644 --- a/git/test/lib/helper.py +++ b/git/test/lib/helper.py @@ -5,23 +5,25 @@ # the BSD License: http://www.opensource.org/licenses/bsd-license.php from __future__ import print_function -import os -from unittest import TestCase -import time -import tempfile +from functools import wraps import io import logging +import os +import tempfile +import textwrap +import time +from unittest import TestCase -from functools import wraps - -from git.util import rmtree from git.compat import string_types, is_win -import textwrap +from git.util import rmtree, HIDE_WINDOWS_KNOWN_ERRORS + +import os.path as osp -osp = os.path.dirname -GIT_REPO = os.environ.get("GIT_PYTHON_TEST_GIT_REPO_BASE", osp(osp(osp(osp(__file__))))) -GIT_DAEMON_PORT = os.environ.get("GIT_PYTHON_TEST_GIT_DAEMON_PORT", "9418") +ospd = osp.dirname + +GIT_REPO = os.environ.get("GIT_PYTHON_TEST_GIT_REPO_BASE", ospd(ospd(ospd(ospd(__file__))))) +GIT_DAEMON_PORT = os.environ.get("GIT_PYTHON_TEST_GIT_DAEMON_PORT", "19418") __all__ = ( 'fixture_path', 'fixture', 'absolute_project_path', 'StringProcessAdapter', @@ -35,8 +37,8 @@ def fixture_path(name): - test_dir = osp(osp(__file__)) - return os.path.join(test_dir, "fixtures", name) + test_dir = ospd(ospd(__file__)) + return osp.join(test_dir, "fixtures", name) def fixture(name): @@ -45,7 +47,7 @@ def fixture(name): def absolute_project_path(): - return os.path.abspath(os.path.join(osp(__file__), "..", "..")) + return osp.abspath(osp.join(osp(__file__), "..", "..")) #} END routines @@ -165,26 +167,31 @@ def repo_creator(self): return argument_passer -def launch_git_daemon(temp_dir, ip, port): +def launch_git_daemon(base_path, ip, port): from git import Git if is_win: ## On MINGW-git, daemon exists in .\Git\mingw64\libexec\git-core\, # but if invoked as 'git daemon', it detaches from parent `git` cmd, # and then CANNOT DIE! # So, invoke it as a single command. - ## Cygwin-git has no daemon. + ## Cygwin-git has no daemon. But it can use MINGW's. # - daemon_cmd = ['git-daemon', temp_dir, + daemon_cmd = ['git-daemon', '--enable=receive-pack', '--listen=%s' % ip, - '--port=%s' % port] + '--port=%s' % port, + '--base-path=%s' % base_path, + base_path] gd = Git().execute(daemon_cmd, as_process=True) else: - gd = Git().daemon(temp_dir, + gd = Git().daemon(base_path, enable='receive-pack', listen=ip, port=port, + base_path=base_path, as_process=True) + # yes, I know ... fortunately, this is always going to work if sleep time is just large enough + time.sleep(0.5) return gd @@ -212,7 +219,8 @@ def case(self, rw_repo, rw_remote_repo) See working dir info in with_rw_repo :note: We attempt to launch our own invocation of git-daemon, which will be shutdown at the end of the test. """ - from git import Remote, GitCommandError + from git import Git, Remote, GitCommandError + assert isinstance(working_tree_ref, string_types), "Decorator requires ref name for working tree checkout" def argument_passer(func): @@ -240,23 +248,36 @@ def remote_repo_creator(self): pass crw.set(section, "receivepack", True) - # initialize the remote - first do it as local remote and pull, then - # we change the url to point to the daemon. The daemon should be started - # by the user, not by us + # Initialize the remote - first do it as local remote and pull, then + # we change the url to point to the daemon. d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) d_remote.fetch() - remote_repo_url = "git://localhost:%s%s" % (GIT_DAEMON_PORT, remote_repo_dir) + base_path, rel_repo_dir = osp.split(remote_repo_dir) + + remote_repo_url = "git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir) with d_remote.config_writer as cw: cw.set('url', remote_repo_url) - temp_dir = osp(_mktemp()) - gd = launch_git_daemon(temp_dir, '127.0.0.1', GIT_DAEMON_PORT) try: - # yes, I know ... fortunately, this is always going to work if sleep time is just large enough - time.sleep(0.5) - # end - + gd = launch_git_daemon(Git.polish_url(base_path), '127.0.0.1', GIT_DAEMON_PORT) + except Exception as ex: + if is_win: + msg = textwrap.dedent(""" + The `git-daemon.exe` must be in PATH. + For MINGW, look into .\Git\mingw64\libexec\git-core\), but problems with paths might appear. + CYGWIN has no daemon, but if one exists, it gets along fine (has also paths problems) + Anyhow, alternatively try starting `git-daemon` manually:""") + else: + msg = "Please try starting `git-daemon` manually:" + msg += textwrap.dedent(""" + git daemon --enable=receive-pack --base-path=%s %s + You can also run the daemon on a different port by passing --port=" + and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to + """ % (base_path, base_path)) + raise AssertionError(ex, msg) + # END make assertion + else: # try to list remotes to diagnoes whether the server is up try: rw_repo.git.ls_remote(d_remote) @@ -283,9 +304,9 @@ def remote_repo_creator(self): git daemon --enable=receive-pack '%s' You can also run the daemon on a different port by passing --port=" and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to - """ % temp_dir) + """ % base_path) from unittest import SkipTest - raise SkipTest(msg) if is_win else AssertionError(msg) + raise SkipTest(msg) if HIDE_WINDOWS_KNOWN_ERRORS else AssertionError(e, msg) # END make assertion # END catch ls remote error @@ -354,7 +375,7 @@ class TestBase(TestCase): def _small_repo_url(self): """:return" a path to a small, clonable repository""" - return os.path.join(self.rorepo.working_tree_dir, 'git/ext/gitdb/gitdb/ext/smmap') + return osp.join(self.rorepo.working_tree_dir, 'git/ext/gitdb/gitdb/ext/smmap') @classmethod def setUpClass(cls): @@ -378,7 +399,7 @@ def _make_file(self, rela_path, data, repo=None): with the given data. Returns absolute path to created file. """ repo = repo or self.rorepo - abs_path = os.path.join(repo.working_tree_dir, rela_path) + abs_path = osp.join(repo.working_tree_dir, rela_path) with open(abs_path, "w") as fp: fp.write(data) return abs_path diff --git a/git/test/test_base.py b/git/test/test_base.py index 2956f3d48..a4382d3ea 100644 --- a/git/test/test_base.py +++ b/git/test/test_base.py @@ -110,17 +110,6 @@ def test_with_rw_repo(self, rw_repo): assert not rw_repo.config_reader("repository").getboolean("core", "bare") assert os.path.isdir(os.path.join(rw_repo.working_tree_dir, 'lib')) - # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, """ - # FIXME: helper.wrapper fails with: - # PermissionError: [WinError 5] Access is denied: - # 'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\ - # master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx' - # AND - # FIXME: git-daemon failing with: - # git.exc.GitCommandError: Cmd('git') failed due to: exit code(128) - # cmdline: git ls-remote daemon_origin - # stderr: 'fatal: bad config line 15 in file .git/config' - # """) @with_rw_and_rw_remote_repo('0.1.6') def test_with_rw_remote_and_rw_repo(self, rw_repo, rw_remote_repo): assert not rw_repo.config_reader("repository").getboolean("core", "bare") diff --git a/git/test/test_docs.py b/git/test/test_docs.py index e2bfcb21f..f3c75f79f 100644 --- a/git/test/test_docs.py +++ b/git/test/test_docs.py @@ -16,7 +16,7 @@ def tearDown(self): import gc gc.collect() - # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, + # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, ## ACTUALLY skipped by `git.submodule.base#L869`. # "FIXME: helper.wrapper fails with: PermissionError: [WinError 5] Access is denied: " # "'C:\\Users\\appveyor\\AppData\\Local\\Temp\\1\\test_work_tree_unsupportedryfa60di\\master_repo\\.git\\objects\\pack\\pack-bc9e0787aef9f69e1591ef38ea0a6f566ec66fe3.idx") # noqa E501 @with_rw_directory diff --git a/git/test/test_remote.py b/git/test/test_remote.py index e0b00e0c5..90bb270d6 100644 --- a/git/test/test_remote.py +++ b/git/test/test_remote.py @@ -30,6 +30,8 @@ import tempfile import os import random +from unittest.case import skipIf +from git.util import HIDE_WINDOWS_KNOWN_ERRORS # assure we have repeatable results random.seed(0) @@ -384,12 +386,7 @@ def _assert_push_and_pull(self, remote, rw_repo, remote_repo): TagReference.delete(rw_repo, new_tag, other_tag) remote.push(":%s" % other_tag.path) - # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, """ - # FIXME: git-daemon failing with: - # git.exc.GitCommandError: Cmd('git') failed due to: exit code(128) - # cmdline: git ls-remote daemon_origin - # stderr: 'fatal: bad config line 15 in file .git/config' - # """) + @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, "FIXME: Freezes!") @with_rw_and_rw_remote_repo('0.1.6') def test_base(self, rw_repo, remote_repo): num_remotes = 0 diff --git a/git/test/test_repo.py b/git/test/test_repo.py index 2c0847e19..e93ea77ec 100644 --- a/git/test/test_repo.py +++ b/git/test/test_repo.py @@ -472,12 +472,17 @@ def test_creation_deletion(self): head = self.rorepo.create_head("new_head", "HEAD~1") self.rorepo.delete_head(head) - tag = self.rorepo.create_tag("new_tag", "HEAD~2") - self.rorepo.delete_tag(tag) + try: + tag = self.rorepo.create_tag("new_tag", "HEAD~2") + finally: + self.rorepo.delete_tag(tag) with self.rorepo.config_writer(): pass - remote = self.rorepo.create_remote("new_remote", "git@server:repo.git") - self.rorepo.delete_remote(remote) + try: + remote = self.rorepo.create_remote("new_remote", "git@server:repo.git") + finally: + self.rorepo.delete_remote(remote) + def test_comparison_and_hash(self): # this is only a preliminary test, more testing done in test_index diff --git a/git/test/test_submodule.py b/git/test/test_submodule.py index e935017fb..902a96b55 100644 --- a/git/test/test_submodule.py +++ b/git/test/test_submodule.py @@ -418,7 +418,7 @@ def _do_base_tests(self, rwrepo): # Error if there is no submodule file here self.failUnlessRaises(IOError, Submodule._config_parser, rwrepo, rwrepo.commit(self.k_no_subm_tag), True) - # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, + # @skipIf(HIDE_WINDOWS_KNOWN_ERRORS, ## ACTUALLY skipped by `git.submodule.base#L869`. # "FIXME: fails with: PermissionError: [WinError 32] The process cannot access the file because" # "it is being used by another process: " # "'C:\\Users\\ankostis\\AppData\\Local\\Temp\\tmp95c3z83bnon_bare_test_base_rw\\git\\ext\\gitdb\\gitdb\\ext\\smmap'") # noqa E501