| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent e6e23ed commit 0bce7cc
2 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -196,16 +196,19 @@ def is_cygwin(cls): | |||
| 196 | 196 | return is_cygwin_git(cls.GIT_PYTHON_GIT_EXECUTABLE) | |
| 197 | 197 | ||
| 198 | 198 | @classmethod | |
| 199 | - def polish_url(cls, url): | ||
| 200 | - if cls.is_cygwin(): | ||
| 199 | + def polish_url(cls, url, is_cygwin=None): | ||
| 200 | + if is_cygwin is None: | ||
| 201 | + is_cygwin = cls.is_cygwin() | ||
| 202 | + | ||
| 203 | + if is_cygwin: | ||
| 204 | + url = cygpath(url) | ||
| 205 | + else: | ||
| 201 | 206 | """Remove any backslahes from urls to be written in config files. | |
| 202 | 207 | ||
| 203 | 208 | Windows might create config-files containing paths with backslashed, | |
| 204 | 209 | but git stops liking them as it will escape the backslashes. | |
| 205 | 210 | Hence we undo the escaping just to be sure. | |
| 206 | 211 | """ | |
| 207 | - url = cygpath(url) | ||
| 208 | - else: | ||
| 209 | 212 | url = url.replace("\\\\", "\\").replace("\\", "/") | |
| 210 | 213 | ||
| 211 | 214 | return url | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -5,6 +5,7 @@ | |||
| 5 | 5 | # the BSD License: http://www.opensource.org/licenses/bsd-license.php | |
| 6 | 6 | from __future__ import print_function | |
| 7 | 7 | ||
| 8 | + import contextlib | ||
| 8 | 9 | from functools import wraps | |
| 9 | 10 | import io | |
| 10 | 11 | import logging | |
@@ -16,7 +17,7 @@ | |||
| 16 | 17 | import unittest | |
| 17 | 18 | ||
| 18 | 19 | from git.compat import string_types, is_win, PY3 | |
| 19 | - from git.util import rmtree | ||
| 20 | + from git.util import rmtree, cwd | ||
| 20 | 21 | ||
| 21 | 22 | import os.path as osp | |
| 22 | 23 | ||
@@ -151,32 +152,67 @@ def repo_creator(self): | |||
| 151 | 152 | return argument_passer | |
| 152 | 153 | ||
| 153 | 154 | ||
| 154 | - def launch_git_daemon(base_path, ip, port): | ||
| 155 | - from git import Git | ||
| 156 | - if is_win: | ||
| 157 | - ## On MINGW-git, daemon exists in .\Git\mingw64\libexec\git-core\, | ||
| 158 | - # but if invoked as 'git daemon', it detaches from parent `git` cmd, | ||
| 159 | - # and then CANNOT DIE! | ||
| 160 | - # So, invoke it as a single command. | ||
| 161 | - ## Cygwin-git has no daemon. But it can use MINGW's. | ||
| 162 | - # | ||
| 163 | - daemon_cmd = ['git-daemon', | ||
| 164 | - '--enable=receive-pack', | ||
| 165 | - '--listen=%s' % ip, | ||
| 166 | - '--port=%s' % port, | ||
| 167 | - '--base-path=%s' % base_path, | ||
| 168 | - base_path] | ||
| 169 | - gd = Git().execute(daemon_cmd, as_process=True) | ||
| 170 | - else: | ||
| 171 | - gd = Git().daemon(base_path, | ||
| 172 | - enable='receive-pack', | ||
| 173 | - listen=ip, | ||
| 174 | - port=port, | ||
| 175 | - base_path=base_path, | ||
| 176 | - as_process=True) | ||
| 177 | - # yes, I know ... fortunately, this is always going to work if sleep time is just large enough | ||
| 178 | - time.sleep(0.5) | ||
| 179 | - return gd | ||
| 155 | + @contextlib.contextmanager | ||
| 156 | + def git_daemon_launched(base_path, ip, port): | ||
| 157 | + from git import Git # Avoid circular deps. | ||
| 158 | + | ||
| 159 | + gd = None | ||
| 160 | + try: | ||
| 161 | + if is_win: | ||
| 162 | + ## On MINGW-git, daemon exists in .\Git\mingw64\libexec\git-core\, | ||
| 163 | + # but if invoked as 'git daemon', it detaches from parent `git` cmd, | ||
| 164 | + # and then CANNOT DIE! | ||
| 165 | + # So, invoke it as a single command. | ||
| 166 | + ## Cygwin-git has no daemon. But it can use MINGW's. | ||
| 167 | + # | ||
| 168 | + daemon_cmd = ['git-daemon', | ||
| 169 | + '--enable=receive-pack', | ||
| 170 | + '--listen=%s' % ip, | ||
| 171 | + '--port=%s' % port, | ||
| 172 | + '--base-path=%s' % base_path, | ||
| 173 | + base_path] | ||
| 174 | + gd = Git().execute(daemon_cmd, as_process=True) | ||
| 175 | + else: | ||
| 176 | + gd = Git().daemon(base_path, | ||
| 177 | + enable='receive-pack', | ||
| 178 | + listen=ip, | ||
| 179 | + port=port, | ||
| 180 | + base_path=base_path, | ||
| 181 | + as_process=True) | ||
| 182 | + # yes, I know ... fortunately, this is always going to work if sleep time is just large enough | ||
| 183 | + time.sleep(0.5 * (1 + is_win)) | ||
| 184 | + | ||
| 185 | + yield | ||
| 186 | + | ||
| 187 | + except Exception as ex: | ||
| 188 | + msg = textwrap.dedent(""" | ||
| 189 | + Launching git-daemon failed due to: %s | ||
| 190 | + Probably test will fail subsequently. | ||
| 191 | + | ||
| 192 | + BUT you may start *git-daemon* manually with this command:" | ||
| 193 | + git daemon --enable=receive-pack --listen=%s --port=%s --base-path=%s %s | ||
| 194 | + You may also run the daemon on a different port by passing --port=<port>" | ||
| 195 | + and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port> | ||
| 196 | + """) | ||
| 197 | + if is_win: | ||
| 198 | + msg += textwrap.dedent(""" | ||
| 199 | + | ||
| 200 | + On Windows, | ||
| 201 | + the `git-daemon.exe` must be in PATH. | ||
| 202 | + For MINGW, look into .\Git\mingw64\libexec\git-core\), but problems with paths might appear. | ||
| 203 | + CYGWIN has no daemon, but if one exists, it gets along fine (but has also paths problems).""") | ||
| 204 | + log.warning(msg, ex, ip, port, base_path, base_path, exc_info=1) | ||
| 205 | + | ||
| 206 | + yield | ||
| 207 | + | ||
| 208 | + finally: | ||
| 209 | + if gd: | ||
| 210 | + try: | ||
| 211 | + log.debug("Killing git-daemon...") | ||
| 212 | + gd.proc.kill() | ||
| 213 | + except Exception as ex: | ||
| 214 | + ## Either it has died (and we're here), or it won't die, again here... | ||
| 215 | + log.debug("Hidden error while Killing git-daemon: %s", ex, exc_info=1) | ||
| 180 | 216 | ||
| 181 | 217 | ||
| 182 | 218 | def with_rw_and_rw_remote_repo(working_tree_ref): | |
@@ -193,10 +229,10 @@ def with_rw_and_rw_remote_repo(working_tree_ref): | |||
| 193 | 229 | directories in it. | |
| 194 | 230 | ||
| 195 | 231 | The following scetch demonstrates this:: | |
| 196 | - rorepo ---<bare clone>---> rw_remote_repo ---<clone>---> rw_repo | ||
| 232 | + rorepo ---<bare clone>---> rw_daemon_repo ---<clone>---> rw_repo | ||
| 197 | 233 | ||
| 198 | 234 | The test case needs to support the following signature:: | |
| 199 | - def case(self, rw_repo, rw_remote_repo) | ||
| 235 | + def case(self, rw_repo, rw_daemon_repo) | ||
| 200 | 236 | ||
| 201 | 237 | This setup allows you to test push and pull scenarios and hooks nicely. | |
| 202 | 238 | ||
@@ -211,94 +247,65 @@ def argument_passer(func): | |||
| 211 | 247 | ||
| 212 | 248 | @wraps(func) | |
| 213 | 249 | def remote_repo_creator(self): | |
| 214 | - remote_repo_dir = tempfile.mktemp("remote_repo_%s" % func.__name__) | ||
| 215 | - repo_dir = tempfile.mktemp("remote_clone_non_bare_repo") | ||
| 250 | + rw_daemon_repo_dir = tempfile.mktemp(prefix="daemon_repo-%s-" % func.__name__) | ||
| 251 | + rw_repo_dir = tempfile.mktemp("daemon_cloned_repo-%s-" % func.__name__) | ||
| 216 | 252 | ||
| 217 | - rw_remote_repo = self.rorepo.clone(remote_repo_dir, shared=True, bare=True) | ||
| 253 | + rw_daemon_repo = self.rorepo.clone(rw_daemon_repo_dir, shared=True, bare=True) | ||
| 218 | 254 | # recursive alternates info ? | |
| 219 | - rw_repo = rw_remote_repo.clone(repo_dir, shared=True, bare=False, n=True) | ||
| 220 | - rw_repo.head.commit = working_tree_ref | ||
| 221 | - rw_repo.head.reference.checkout() | ||
| 222 | - | ||
| 223 | - # prepare for git-daemon | ||
| 224 | - rw_remote_repo.daemon_export = True | ||
| 225 | - | ||
| 226 | - # this thing is just annoying ! | ||
| 227 | - with rw_remote_repo.config_writer() as crw: | ||
| 228 | - section = "daemon" | ||
| 229 | - try: | ||
| 230 | - crw.add_section(section) | ||
| 231 | - except Exception: | ||
| 232 | - pass | ||
| 233 | - crw.set(section, "receivepack", True) | ||
| 234 | - | ||
| 235 | - # Initialize the remote - first do it as local remote and pull, then | ||
| 236 | - # we change the url to point to the daemon. | ||
| 237 | - d_remote = Remote.create(rw_repo, "daemon_origin", remote_repo_dir) | ||
| 238 | - d_remote.fetch() | ||
| 239 | - | ||
| 240 | - base_path, rel_repo_dir = osp.split(remote_repo_dir) | ||
| 241 | - | ||
| 242 | - remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir)) | ||
| 243 | - with d_remote.config_writer as cw: | ||
| 244 | - cw.set('url', remote_repo_url) | ||
| 245 | - | ||
| 255 | + rw_repo = rw_daemon_repo.clone(rw_repo_dir, shared=True, bare=False, n=True) | ||
| 246 | 256 | try: | |
| 247 | - gd = launch_git_daemon(Git.polish_url(base_path), '127.0.0.1', GIT_DAEMON_PORT) | ||
| 248 | - except Exception as ex: | ||
| 249 | - if is_win: | ||
| 250 | - msg = textwrap.dedent(""" | ||
| 251 | - The `git-daemon.exe` must be in PATH. | ||
| 252 | - For MINGW, look into .\Git\mingw64\libexec\git-core\), but problems with paths might appear. | ||
| 253 | - CYGWIN has no daemon, but if one exists, it gets along fine (has also paths problems) | ||
| 254 | - Anyhow, alternatively try starting `git-daemon` manually:""") | ||
| 255 | - else: | ||
| 256 | - msg = "Please try starting `git-daemon` manually:" | ||
| 257 | - msg += textwrap.dedent(""" | ||
| 258 | - git daemon --enable=receive-pack --base-path=%s %s | ||
| 259 | - You can also run the daemon on a different port by passing --port=<port>" | ||
| 260 | - and setting the environment variable GIT_PYTHON_TEST_GIT_DAEMON_PORT to <port> | ||
| 261 | - """ % (base_path, base_path)) | ||
| 262 | - raise AssertionError(ex, msg) | ||
| 263 | - # END make assertion | ||
| 264 | - else: | ||
| 265 | - # Try listing remotes, to diagnose whether the daemon is up. | ||
| 266 | - rw_repo.git.ls_remote(d_remote) | ||
| 267 | - | ||
| 268 | - # adjust working dir | ||
| 269 | - prev_cwd = os.getcwd() | ||
| 270 | - os.chdir(rw_repo.working_dir) | ||
| 257 | + rw_repo.head.commit = working_tree_ref | ||
| 258 | + rw_repo.head.reference.checkout() | ||
| 271 | 259 | ||
| 272 | - try: | ||
| 273 | - return func(self, rw_repo, rw_remote_repo) | ||
| 274 | - except: | ||
| 275 | - log.info("Keeping repos after failure: repo_dir = %s, remote_repo_dir = %s", | ||
| 276 | - repo_dir, remote_repo_dir) | ||
| 277 | - repo_dir = remote_repo_dir = None | ||
| 278 | - raise | ||
| 279 | - finally: | ||
| 280 | - os.chdir(prev_cwd) | ||
| 260 | + # prepare for git-daemon | ||
| 261 | + rw_daemon_repo.daemon_export = True | ||
| 262 | + | ||
| 263 | + # this thing is just annoying ! | ||
| 264 | + with rw_daemon_repo.config_writer() as crw: | ||
| 265 | + section = "daemon" | ||
| 266 | + try: | ||
| 267 | + crw.add_section(section) | ||
| 268 | + except Exception: | ||
| 269 | + pass | ||
| 270 | + crw.set(section, "receivepack", True) | ||
| 271 | + | ||
| 272 | + # Initialize the remote - first do it as local remote and pull, then | ||
| 273 | + # we change the url to point to the daemon. | ||
| 274 | + d_remote = Remote.create(rw_repo, "daemon_origin", rw_daemon_repo_dir) | ||
| 275 | + d_remote.fetch() | ||
| 276 | + | ||
| 277 | + base_daemon_path, rel_repo_dir = osp.split(rw_daemon_repo_dir) | ||
| 278 | + | ||
| 279 | + remote_repo_url = Git.polish_url("git://localhost:%s/%s" % (GIT_DAEMON_PORT, rel_repo_dir)) | ||
| 280 | + with d_remote.config_writer as cw: | ||
| 281 | + cw.set('url', remote_repo_url) | ||
| 282 | + | ||
| 283 | + with git_daemon_launched(Git.polish_url(base_daemon_path, is_cygwin=False), # No daemon in Cygwin. | ||
| 284 | + '127.0.0.1', | ||
| 285 | + GIT_DAEMON_PORT): | ||
| 286 | + # Try listing remotes, to diagnose whether the daemon is up. | ||
| 287 | + rw_repo.git.ls_remote(d_remote) | ||
| 288 | + | ||
| 289 | + with cwd(rw_repo.working_dir): | ||
| 290 | + try: | ||
| 291 | + return func(self, rw_repo, rw_daemon_repo) | ||
| 292 | + except: | ||
| 293 | + log.info("Keeping repos after failure: \n rw_repo_dir: %s \n rw_daemon_repo_dir: %s", | ||
| 294 | + rw_repo_dir, rw_daemon_repo_dir) | ||
| 295 | + rw_repo_dir = rw_daemon_repo_dir = None | ||
| 296 | + raise | ||
| 281 | 297 | ||
| 282 | 298 | finally: | |
| 283 | - try: | ||
| 284 | - log.debug("Killing git-daemon...") | ||
| 285 | - gd.proc.kill() | ||
| 286 | - except: | ||
| 287 | - ## Either it has died (and we're here), or it won't die, again here... | ||
| 288 | - pass | ||
| 289 | - | ||
| 290 | 299 | rw_repo.git.clear_cache() | |
| 291 | - rw_remote_repo.git.clear_cache() | ||
| 292 | - rw_repo = rw_remote_repo = None | ||
| 300 | + rw_daemon_repo.git.clear_cache() | ||
| 301 | + del rw_repo | ||
| 302 | + del rw_daemon_repo | ||
| 293 | 303 | import gc | |
| 294 | 304 | gc.collect() | |
| 295 | - if repo_dir: | ||
| 296 | - rmtree(repo_dir) | ||
| 297 | - if remote_repo_dir: | ||
| 298 | - rmtree(remote_repo_dir) | ||
| 299 | - | ||
| 300 | - if gd is not None: | ||
| 301 | - gd.proc.wait() | ||
| 305 | + if rw_repo_dir: | ||
| 306 | + rmtree(rw_repo_dir) | ||
| 307 | + if rw_daemon_repo_dir: | ||
| 308 | + rmtree(rw_daemon_repo_dir) | ||
| 302 | 309 | # END cleanup | |
| 303 | 310 | # END bare repo creator | |
| 304 | 311 | return remote_repo_creator | |
| Back | FazBrowse Home | New Git URL |
0 commit comments