def disable_ff_and_make_dummy_commit(self): # disable non-fast-forward pushes to the server dest = repo.Repo(os.path.join(self.gitroot, 'dest')) run_git_or_fail(['config', 'receive.denyNonFastForwards', 'true'], cwd=dest.path) commit_id = self.make_dummy_commit(dest) return dest, commit_id
def test_push_to_dulwich(self): self.import_repos() self.assertReposNotEqual(self._old_repo, self._new_repo) port = self._start_server(self._old_repo) run_git_or_fail(['push', self.url(port)] + self.branch_args(), cwd=self._new_repo.path) self.assertReposEqual(self._old_repo, self._new_repo)
def setUp(self): CompatTestCase.setUp(self) DulwichClientTestBase.setUp(self) self._httpd = HTTPGitServer(("localhost", 0), self.gitroot) self.addCleanup(self._httpd.shutdown) threading.Thread(target=self._httpd.serve_forever).start() run_git_or_fail(['config', 'http.uploadpack', 'true'], cwd=self.dest) run_git_or_fail(['config', 'http.receivepack', 'true'], cwd=self.dest)
def test_fetch_from_dulwich(self): self.import_repos() self.assertReposNotEqual(self._old_repo, self._new_repo) port = self._start_server(self._new_repo) run_git_or_fail(['fetch', self.url(port)] + self.branch_args(), cwd=self._old_repo.path) # flush the pack cache so any new packs are picked up self._old_repo.object_store._pack_cache_time = 0 self.assertReposEqual(self._old_repo, self._new_repo)
def test_push_to_dulwich_remove_branch(self): self._old_repo = self.import_repo('server_old.export') self._new_repo = self.import_repo('server_old.export') self.assertReposEqual(self._old_repo, self._new_repo) port = self._start_server(self._old_repo) run_git_or_fail(['push', self.url(port), ":master"], cwd=self._new_repo.path) self.assertEqual(list(self._old_repo.get_refs().keys()), [b"refs/heads/branch"])
def test_push_to_dulwich_issue_88_standard(self): # Same thing, but we reverse the role of the server/client # and do a push instead. self._source_repo = self.import_repo( 'issue88_expect_ack_nak_client.export') self._client_repo = self.import_repo( 'issue88_expect_ack_nak_server.export') port = self._start_server(self._source_repo) run_git_or_fail(['push', self.url(port), 'master'], cwd=self._client_repo.path) self.assertReposEqual(self._source_repo, self._client_repo)
def create_new_worktree(self, repo_dir, branch): """Create a new worktree using git-worktree. :param repo_dir: The directory of the main working tree. :param branch: The branch or commit to checkout in the new worktree. :returns: The path to the new working tree. """ temp_dir = tempfile.mkdtemp() run_git_or_fail(['worktree', 'add', temp_dir, branch], cwd=repo_dir) self.addCleanup(rmtree_ro, temp_dir) return temp_dir
def test_clone_from_dulwich_empty(self): old_repo_dir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, old_repo_dir) self._old_repo = Repo.init_bare(old_repo_dir) port = self._start_server(self._old_repo) new_repo_base_dir = tempfile.mkdtemp() self.addCleanup(shutil.rmtree, new_repo_base_dir) new_repo_dir = os.path.join(new_repo_base_dir, 'empty_new') run_git_or_fail(['clone', self.url(port), new_repo_dir], cwd=new_repo_base_dir) new_repo = Repo(new_repo_dir) self.assertReposEqual(self._old_repo, new_repo)
def test_fetch_from_dulwich_issue_88_standard(self): # Basically an integration test to see that the ACK/NAK # generation works on repos with common head. self._source_repo = self.import_repo( 'issue88_expect_ack_nak_server.export') self._client_repo = self.import_repo( 'issue88_expect_ack_nak_client.export') port = self._start_server(self._source_repo) run_git_or_fail(['fetch', self.url(port), 'master'], cwd=self._client_repo.path) self.assertObjectStoreEqual(self._source_repo.object_store, self._client_repo.object_store)
def test_delta_medium_object(self): # This tests an object set that will have a copy operation # 2**20 in size. with self.get_pack(pack1_sha) as orig_pack: orig_blob = orig_pack[a_sha] new_blob = Blob() new_blob.data = orig_blob.data + (b'x' * 2**20) new_blob_2 = Blob() new_blob_2.data = new_blob.data + b'y' all_to_pack = list(orig_pack.pack_tuples()) + [(new_blob, None), (new_blob_2, None)] pack_path = os.path.join(self._tempdir, 'pack_with_deltas') write_pack(pack_path, all_to_pack, deltify=True) output = run_git_or_fail(['verify-pack', '-v', pack_path]) self.assertEqual(set(x[0].id for x in all_to_pack), _git_verify_pack_object_list(output)) # We specifically made a new blob that should be a delta # against the blob a_sha, so make sure we really got only 3 # non-delta objects: got_non_delta = int(_NON_DELTA_RE.search(output).group('non_delta')) self.assertEqual( 3, got_non_delta, 'Expected 3 non-delta objects, got %d' % got_non_delta) # We expect one object to have a delta chain length of two # (new_blob_2), so let's verify that actually happens: self.assertIn(b'chain length = 2', output)
def test_fetch_from_dulwich_issue_88_alternative(self): # likewise, but the case where the two repos have no common parent self._source_repo = self.import_repo( 'issue88_expect_ack_nak_other.export') self._client_repo = self.import_repo( 'issue88_expect_ack_nak_client.export') port = self._start_server(self._source_repo) self.assertRaises(KeyError, self._client_repo.get_object, b'02a14da1fc1fc13389bbf32f0af7d8899f2b2323') run_git_or_fail(['fetch', self.url(port), 'master'], cwd=self._client_repo.path) self.assertEqual( b'commit', self._client_repo.get_object( b'02a14da1fc1fc13389bbf32f0af7d8899f2b2323').type_name)
def test_copy(self): with self.get_pack(pack1_sha) as origpack: self.assertSucceeds(origpack.index.check) pack_path = os.path.join(self._tempdir, "Elch") write_pack(pack_path, origpack.pack_tuples()) output = run_git_or_fail(['verify-pack', '-v', pack_path]) orig_shas = set(o.id for o in origpack.iterobjects()) self.assertEqual(orig_shas, _git_verify_pack_object_list(output))
def test_git_worktree_list(self): # 'git worktree list' was introduced in 2.7.0 require_git_version((2, 7, 0)) output = run_git_or_fail(['worktree', 'list'], cwd=self._repo.path) worktrees = self._parse_worktree_list(output) self.assertEqual(len(worktrees), self._number_of_working_tree) self.assertEqual(worktrees[0][1], '(bare)') self.assertEqual(os.path.normcase(worktrees[0][0]), os.path.normcase(self._mainworktree_repo.path)) output = run_git_or_fail(['worktree', 'list'], cwd=self._mainworktree_repo.path) worktrees = self._parse_worktree_list(output) self.assertEqual(len(worktrees), self._number_of_working_tree) self.assertEqual(worktrees[0][1], '(bare)') self.assertEqual(os.path.normcase(worktrees[0][0]), os.path.normcase(self._mainworktree_repo.path))
def test_new_shallow_clone_from_dulwich(self): require_git_version(self.min_single_branch_version) self._source_repo = self.import_repo('server_new.export') self._stub_repo = _StubRepo('shallow') self.addCleanup(tear_down_repo, self._stub_repo) port = self._start_server(self._source_repo) # Fetch at depth 1 run_git_or_fail([ 'clone', '--mirror', '--depth=1', '--no-single-branch', self.url(port), self._stub_repo.path ]) clone = self._stub_repo = Repo(self._stub_repo.path) expected_shallow = [ b'35e0b59e187dd72a0af294aedffc213eaa4d03ff', b'514dc6d3fbfe77361bcaef320c4d21b72bc10be9' ] self.assertEqual(expected_shallow, _get_shallow(clone)) self.assertReposNotEqual(clone, self._source_repo)
def test_fetch_full_depth_into_shallow_clone_from_dulwich(self): require_git_version(self.min_single_branch_version) self._source_repo = self.import_repo('server_new.export') self._stub_repo = _StubRepo('shallow') self.addCleanup(tear_down_repo, self._stub_repo) port = self._start_server(self._source_repo) # Fetch at depth 2 run_git_or_fail([ 'clone', '--mirror', '--depth=2', '--no-single-branch', self.url(port), self._stub_repo.path ]) clone = self._stub_repo = Repo(self._stub_repo.path) # Fetching at the same depth is a no-op. run_git_or_fail( ['fetch', '--depth=2', self.url(port)] + self.branch_args(), cwd=self._stub_repo.path) # The whole repo only has depth 4, so it should equal server_new. run_git_or_fail( ['fetch', '--depth=4', self.url(port)] + self.branch_args(), cwd=self._stub_repo.path) self.assertEqual([], _get_shallow(clone)) self.assertReposEqual(clone, self._source_repo)
def test_shallow_clone_from_git_is_identical(self): require_git_version(self.min_single_branch_version) self._source_repo = self.import_repo('server_new.export') self._stub_repo_git = _StubRepo('shallow-git') self.addCleanup(tear_down_repo, self._stub_repo_git) self._stub_repo_dw = _StubRepo('shallow-dw') self.addCleanup(tear_down_repo, self._stub_repo_dw) # shallow clone using stock git, then using dulwich run_git_or_fail([ 'clone', '--mirror', '--depth=1', '--no-single-branch', 'file://' + self._source_repo.path, self._stub_repo_git.path ]) port = self._start_server(self._source_repo) run_git_or_fail([ 'clone', '--mirror', '--depth=1', '--no-single-branch', self.url(port), self._stub_repo_dw.path ]) # compare the two clones; they should be equal self.assertReposEqual(Repo(self._stub_repo_git.path), Repo(self._stub_repo_dw.path))
def test_fetch_same_depth_into_shallow_clone_from_dulwich(self): require_git_version(self.min_single_branch_version) self._source_repo = self.import_repo('server_new.export') self._stub_repo = _StubRepo('shallow') self.addCleanup(tear_down_repo, self._stub_repo) port = self._start_server(self._source_repo) # Fetch at depth 2 run_git_or_fail([ 'clone', '--mirror', '--depth=2', '--no-single-branch', self.url(port), self._stub_repo.path ]) clone = self._stub_repo = Repo(self._stub_repo.path) # Fetching at the same depth is a no-op. run_git_or_fail( ['fetch', '--depth=2', self.url(port)] + self.branch_args(), cwd=self._stub_repo.path) expected_shallow = [ b'94de09a530df27ac3bb613aaecdd539e0a0655e1', b'da5cd81e1883c62a25bb37c4d1f8ad965b29bf8d' ] self.assertEqual(expected_shallow, _get_shallow(clone)) self.assertReposNotEqual(clone, self._source_repo)
def test_deltas_work(self): with self.get_pack(pack1_sha) as orig_pack: orig_blob = orig_pack[a_sha] new_blob = Blob() new_blob.data = orig_blob.data + b'x' all_to_pack = list(orig_pack.pack_tuples()) + [(new_blob, None)] pack_path = os.path.join(self._tempdir, 'pack_with_deltas') write_pack(pack_path, all_to_pack, deltify=True) output = run_git_or_fail(['verify-pack', '-v', pack_path]) self.assertEqual(set(x[0].id for x in all_to_pack), _git_verify_pack_object_list(output)) # We specifically made a new blob that should be a delta # against the blob a_sha, so make sure we really got only 3 # non-delta objects: got_non_delta = int(_NON_DELTA_RE.search(output).group('non_delta')) self.assertEqual( 3, got_non_delta, 'Expected 3 non-delta objects, got %d' % got_non_delta)
def test_delta_large_object(self): # This tests an object set that will have a copy operation # 2**25 in size. This is a copy large enough that it requires # two copy operations in git's binary delta format. raise SkipTest('skipping slow, large test') with self.get_pack(pack1_sha) as orig_pack: new_blob = Blob() new_blob.data = 'big blob' + ('x' * 2**25) new_blob_2 = Blob() new_blob_2.data = new_blob.data + 'y' all_to_pack = list(orig_pack.pack_tuples()) + [(new_blob, None), (new_blob_2, None)] pack_path = os.path.join(self._tempdir, "pack_with_deltas") write_pack(pack_path, all_to_pack, deltify=True) output = run_git_or_fail(['verify-pack', '-v', pack_path]) self.assertEqual(set(x[0].id for x in all_to_pack), _git_verify_pack_object_list(output)) # We specifically made a new blob that should be a delta # against the blob a_sha, so make sure we really got only 4 # non-delta objects: got_non_delta = int(_NON_DELTA_RE.search(output).group('non_delta')) self.assertEqual( 4, got_non_delta, 'Expected 4 non-delta objects, got %d' % got_non_delta)
def run_backend(self): """Call out to git http-backend.""" # Based on CGIHTTPServer.CGIHTTPRequestHandler.run_cgi: # Copyright (c) 2001-2010 Python Software Foundation; # All Rights Reserved # Licensed under the Python Software Foundation License. rest = self.path # find an explicit query string, if present. i = rest.rfind('?') if i >= 0: rest, query = rest[:i], rest[i+1:] else: query = '' env = copy.deepcopy(os.environ) env['SERVER_SOFTWARE'] = self.version_string() env['SERVER_NAME'] = self.server.server_name env['GATEWAY_INTERFACE'] = 'CGI/1.1' env['SERVER_PROTOCOL'] = self.protocol_version env['SERVER_PORT'] = str(self.server.server_port) env['GIT_PROJECT_ROOT'] = self.server.root_path env["GIT_HTTP_EXPORT_ALL"] = "1" env['REQUEST_METHOD'] = self.command uqrest = unquote(rest) env['PATH_INFO'] = uqrest env['SCRIPT_NAME'] = "/" if query: env['QUERY_STRING'] = query host = self.address_string() if host != self.client_address[0]: env['REMOTE_HOST'] = host env['REMOTE_ADDR'] = self.client_address[0] authorization = self.headers.get("authorization") if authorization: authorization = authorization.split() if len(authorization) == 2: import base64 import binascii env['AUTH_TYPE'] = authorization[0] if authorization[0].lower() == "basic": try: authorization = base64.decodestring(authorization[1]) except binascii.Error: pass else: authorization = authorization.split(':') if len(authorization) == 2: env['REMOTE_USER'] = authorization[0] # XXX REMOTE_IDENT content_type = self.headers.get('content-type') if content_type: env['CONTENT_TYPE'] = content_type length = self.headers.get('content-length') if length: env['CONTENT_LENGTH'] = length referer = self.headers.get('referer') if referer: env['HTTP_REFERER'] = referer accept = [] for line in self.headers.getallmatchingheaders('accept'): if line[:1] in "\t\n\r ": accept.append(line.strip()) else: accept = accept + line[7:].split(',') env['HTTP_ACCEPT'] = ','.join(accept) ua = self.headers.get('user-agent') if ua: env['HTTP_USER_AGENT'] = ua co = self.headers.get('cookie') if co: env['HTTP_COOKIE'] = co # XXX Other HTTP_* headers # Since we're setting the env in the parent, provide empty # values to override previously set values for k in ('QUERY_STRING', 'REMOTE_HOST', 'CONTENT_LENGTH', 'HTTP_USER_AGENT', 'HTTP_COOKIE', 'HTTP_REFERER'): env.setdefault(k, "") self.wfile.write(b"HTTP/1.1 200 Script output follows\r\n") self.wfile.write( ("Server: %s\r\n" % self.server.server_name).encode('ascii')) self.wfile.write( ("Date: %s\r\n" % self.date_time_string()).encode('ascii')) decoded_query = query.replace('+', ' ') try: nbytes = int(length) except (TypeError, ValueError): nbytes = 0 if self.command.lower() == "post" and nbytes > 0: data = self.rfile.read(nbytes) else: data = None # throw away additional data [see bug #427345] while select.select([self.rfile._sock], [], [], 0)[0]: if not self.rfile._sock.recv(1): break args = ['http-backend'] if '=' not in decoded_query: args.append(decoded_query) stdout = run_git_or_fail( args, input=data, env=env, stderr=subprocess.PIPE) self.wfile.write(stdout)
def setUp(self): self.gitroot = os.path.dirname( import_repo_to_dir('server_new.export').rstrip(os.sep)) self.dest = os.path.join(self.gitroot, 'dest') file.ensure_dir_exists(self.dest) run_git_or_fail(['init', '--quiet', '--bare'], cwd=self.dest)
def _run_git(self, args): return run_git_or_fail(args, cwd=self._repo.path)
def test_lsremote_from_dulwich(self): self._repo = self.import_repo('server_old.export') port = self._start_server(self._repo) o = run_git_or_fail(['ls-remote', self.url(port)]) self.assertEqual(len(o.split(b'\n')), 4)