def with_rw_and_rw_remote_repo(working_tree_ref):
    """
    Same as with_rw_repo, but also provides a writable remote repository from which the
    rw_repo has been forked as well as a handle for a git-daemon that may be started to
    run the remote_repo.
    The remote repository was cloned as bare repository from the rorepo, wheras
    the rw repo has a working tree and was cloned from the remote repository.

    remote_repo has two remotes: origin and daemon_origin. One uses a local url,
    the other uses a server url. The daemon setup must be done on system level
    and should be an inetd service that serves tempdir.gettempdir() and all
    directories in it.

    The following scetch demonstrates this::
     rorepo ---<bare clone>---> rw_remote_repo ---<clone>---> rw_repo

    The test case needs to support the following signature::
        def case(self, rw_repo, rw_remote_repo)

    This setup allows you to test push and pull scenarios and hooks nicely.

    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.
    """
    assert isinstance(working_tree_ref, string_types), "Decorator requires ref name for working tree checkout"

    def argument_passer(func):
        def remote_repo_creator(self):
            remote_repo_dir = _mktemp("remote_repo_%s" % func.__name__)
            repo_dir = _mktemp("remote_clone_non_bare_repo")

            rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True)
            # recursive alternates info ?
            rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True)
            rw_repo.head.commit = working_tree_ref
            rw_repo.head.reference.checkout()

            # prepare for git-daemon
            rw_remote_repo.daemon_export = True

            # this thing is just annoying !
            crw = rw_remote_repo.config_writer()
            section = "daemon"
            try:
                crw.add_section(section)
            except Exception:
                pass
            crw.set(section, "receivepack", True)
            # release lock
            crw.release()
            del(crw)

            # 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
            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)

            d_remote.config_writer.set('url', remote_repo_url)

            temp_dir = osp(_mktemp())
            # On windows, this will fail ... we deal with failures anyway and default to telling the user to do it
            try:
                gd = Git().daemon(temp_dir, enable='receive-pack', listen='127.0.0.1', port=GIT_DAEMON_PORT,
                                  as_process=True)
                # yes, I know ... fortunately, this is always going to work if sleep time is just large enough
                time.sleep(0.5)
            except Exception:
                gd = None
            # end

            # try to list remotes to diagnoes whether the server is up
            try:
                rw_repo.git.ls_remote(d_remote)
            except GitCommandError as e:
                # We assume in good faith that we didn't start the daemon - but make sure we kill it anyway
                # Of course we expect it to work here already, but maybe there are timing constraints
                # on some platforms ?
                if gd is not None:
                    os.kill(gd.proc.pid, 15)
                print(str(e))
                if os.name == 'nt':
                    msg = "git-daemon needs to run this test, but windows does not have one. "
                    msg += 'Otherwise, run: git-daemon "%s"' % temp_dir
                    raise AssertionError(msg)
                else:
                    msg = 'Please start a git-daemon to run this test, execute: git daemon --enable=receive-pack "%s"'
                    msg += 'You can also run the daemon on a different port by passing --port=<port>'
                    msg += 'and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port>'
                    msg %= temp_dir
                    raise AssertionError(msg)
                # END make assertion
            # END catch ls remote error

            # adjust working dir
            prev_cwd = os.getcwd()
            os.chdir(rw_repo.working_dir)
            try:
                try:
                    return func(self, rw_repo, rw_remote_repo)
                except:
                    print("Keeping repos after failure: repo_dir = %s, remote_repo_dir = %s"
                          % (repo_dir, remote_repo_dir), file=sys.stderr)
                    repo_dir = remote_repo_dir = None
                    raise
            finally:
                # gd.proc.kill() ... no idea why that doesn't work
                if gd is not None:
                    os.kill(gd.proc.pid, 15)

                os.chdir(prev_cwd)
                rw_repo.git.clear_cache()
                rw_remote_repo.git.clear_cache()
                if repo_dir:
                    shutil.rmtree(repo_dir, onerror=_rmtree_onerror)
                if remote_repo_dir:
                    shutil.rmtree(remote_repo_dir, onerror=_rmtree_onerror)

                if gd is not None:
                    gd.proc.wait()
            # END cleanup
        # END bare repo creator
        remote_repo_creator.__name__ = func.__name__
        return remote_repo_creator
        # END remote repo creator
    # END argument parsser

    return argument_passer

#} END decorators
dataset/ETHPy150Open gitpython-developers/GitPython/git/test/lib/helper.py/with_rw_and_rw_remote_repo/original