Commit Diff


commit - b415021b0a3fb9b3ea738686aac6866dc0ce6c82
commit + d40c5cfe2c07824595c5d582d3268a1a322027dd
blob - 74590c1f702b3e36cf0dc6d94516da09968c4648
blob + 47ab4b14ade7edea90dad1b28eff84fcded96e9e
--- dulwich/cli.py
+++ dulwich/cli.py
@@ -37,12 +37,13 @@ from getopt import getopt
 from typing import Dict, Optional, Type
 
 from dulwich import porcelain
-from dulwich.client import GitProtocolError, get_transport_and_path
-from dulwich.errors import ApplyDeltaError
-from dulwich.index import Index
-from dulwich.objectspec import parse_commit
-from dulwich.pack import Pack, sha_to_hex
-from dulwich.repo import Repo
+
+from .client import GitProtocolError, get_transport_and_path
+from .errors import ApplyDeltaError
+from .index import Index
+from .objectspec import parse_commit
+from .pack import Pack, sha_to_hex
+from .repo import Repo
 
 
 def signal_int(signal, frame):
@@ -383,8 +384,9 @@ class cmd_reset(Command):
 class cmd_daemon(Command):
     def run(self, args):
         from dulwich import log_utils
-        from dulwich.protocol import TCP_GIT_PORT
 
+        from .protocol import TCP_GIT_PORT
+
         parser = optparse.OptionParser()
         parser.add_option(
             "-l",
blob - 6295b0472fed5a8188ce18a1ea420bd0d7c97171
blob + 4e86146af43859ee13a3017c0e3bcc6f331d45d6
--- dulwich/client.py
+++ dulwich/client.py
@@ -56,30 +56,28 @@ if TYPE_CHECKING:
     import urllib3
 
 import dulwich
-from dulwich.config import Config, apply_instead_of, get_xdg_config_home_path
-from dulwich.errors import GitProtocolError, NotGitRepository, SendPackError
-from dulwich.pack import (PACK_SPOOL_FILE_MAX_SIZE, PackChunkGenerator,
-                          UnpackedObject, write_pack_from_container)
-from dulwich.protocol import (_RBUFSIZE, CAPABILITIES_REF, CAPABILITY_AGENT,
-                              CAPABILITY_DELETE_REFS, CAPABILITY_INCLUDE_TAG,
-                              CAPABILITY_MULTI_ACK,
-                              CAPABILITY_MULTI_ACK_DETAILED,
-                              CAPABILITY_OFS_DELTA, CAPABILITY_QUIET,
-                              CAPABILITY_REPORT_STATUS, CAPABILITY_SHALLOW,
-                              CAPABILITY_SIDE_BAND_64K, CAPABILITY_SYMREF,
-                              CAPABILITY_THIN_PACK, COMMAND_DEEPEN,
-                              COMMAND_DONE, COMMAND_HAVE, COMMAND_SHALLOW,
-                              COMMAND_UNSHALLOW, COMMAND_WANT,
-                              KNOWN_RECEIVE_CAPABILITIES,
-                              KNOWN_UPLOAD_CAPABILITIES,
-                              SIDE_BAND_CHANNEL_DATA, SIDE_BAND_CHANNEL_FATAL,
-                              SIDE_BAND_CHANNEL_PROGRESS, TCP_GIT_PORT,
-                              ZERO_SHA, HangupException, PktLineParser,
-                              Protocol, agent_string, capability_agent,
-                              extract_capabilities, extract_capability_names,
-                              parse_capability, pkt_line)
-from dulwich.refs import PEELED_TAG_SUFFIX, _import_remote_refs, read_info_refs
-from dulwich.repo import Repo
+
+from .config import Config, apply_instead_of, get_xdg_config_home_path
+from .errors import GitProtocolError, NotGitRepository, SendPackError
+from .pack import (PACK_SPOOL_FILE_MAX_SIZE, PackChunkGenerator,
+                   UnpackedObject, write_pack_from_container)
+from .protocol import (_RBUFSIZE, CAPABILITIES_REF, CAPABILITY_AGENT,
+                       CAPABILITY_DELETE_REFS, CAPABILITY_INCLUDE_TAG,
+                       CAPABILITY_MULTI_ACK, CAPABILITY_MULTI_ACK_DETAILED,
+                       CAPABILITY_OFS_DELTA, CAPABILITY_QUIET,
+                       CAPABILITY_REPORT_STATUS, CAPABILITY_SHALLOW,
+                       CAPABILITY_SIDE_BAND_64K, CAPABILITY_SYMREF,
+                       CAPABILITY_THIN_PACK, COMMAND_DEEPEN, COMMAND_DONE,
+                       COMMAND_HAVE, COMMAND_SHALLOW, COMMAND_UNSHALLOW,
+                       COMMAND_WANT, KNOWN_RECEIVE_CAPABILITIES,
+                       KNOWN_UPLOAD_CAPABILITIES, SIDE_BAND_CHANNEL_DATA,
+                       SIDE_BAND_CHANNEL_FATAL, SIDE_BAND_CHANNEL_PROGRESS,
+                       TCP_GIT_PORT, ZERO_SHA, HangupException, PktLineParser,
+                       Protocol, agent_string, capability_agent,
+                       extract_capabilities, extract_capability_names,
+                       parse_capability, pkt_line)
+from .refs import PEELED_TAG_SUFFIX, _import_remote_refs, read_info_refs
+from .repo import Repo
 
 # url2pathname is lazily imported
 url2pathname = None
@@ -1663,7 +1661,7 @@ def ParamikoSSHVendor(**kwargs):
         "ParamikoSSHVendor has been moved to dulwich.contrib.paramiko_vendor.",
         DeprecationWarning,
     )
-    from dulwich.contrib.paramiko_vendor import ParamikoSSHVendor
+    from .contrib.paramiko_vendor import ParamikoSSHVendor
 
     return ParamikoSSHVendor(**kwargs)
 
blob - 511bc3ce273087fd5733e3ee3895bd3185bfb55e
blob + 974239dbc3ade9def06497618187e7f1a294e31c
--- dulwich/config.py
+++ dulwich/config.py
@@ -26,13 +26,13 @@ TODO:
    subsections
 """
 
-from contextlib import suppress
 import os
 import sys
+from contextlib import suppress
 from typing import (BinaryIO, Iterable, Iterator, KeysView, List,
                     MutableMapping, Optional, Tuple, Union, overload)
 
-from dulwich.file import GitFile
+from .file import GitFile
 
 SENTINEL = object()
 
blob - 2c966a10b02a29a0939aace3500a3b6391ffe603
blob + fc3eefdc88c697175cf38f78242d7467e1f45acd
--- dulwich/contrib/release_robot.py
+++ dulwich/contrib/release_robot.py
@@ -49,7 +49,7 @@ import re
 import sys
 import time
 
-from dulwich.repo import Repo
+from ..repo import Repo
 
 # CONSTANTS
 PROJDIR = "."
blob - 73068f9e4cd253353985fb252533f8c341278440
blob + db937a57eeb5fd5b1c4878d3d3b1d8e8d4f0e33f
--- dulwich/contrib/requests_vendor.py
+++ dulwich/contrib/requests_vendor.py
@@ -33,9 +33,9 @@ from io import BytesIO
 
 from requests import Session
 
-from dulwich.client import (AbstractHttpGitClient, HTTPProxyUnauthorized,
-                            HTTPUnauthorized, default_user_agent_string)
-from dulwich.errors import GitProtocolError, NotGitRepository
+from ..client import (AbstractHttpGitClient, HTTPProxyUnauthorized,
+                      HTTPUnauthorized, default_user_agent_string)
+from ..errors import GitProtocolError, NotGitRepository
 
 
 class RequestsHttpGitClient(AbstractHttpGitClient):
blob - 9f961a6968e4bde16f4fd42516659664b9ae4cec
blob + 263a14f3a78e6d941c0be5482b85d79537922efc
--- dulwich/contrib/swift.py
+++ dulwich/contrib/swift.py
@@ -39,19 +39,18 @@ from io import BytesIO
 
 from geventhttpclient import HTTPClient
 
-from dulwich.greenthreads import GreenThreadsMissingObjectFinder
-from dulwich.lru_cache import LRUSizeCache
-from dulwich.object_store import INFODIR, PACKDIR, PackBasedObjectStore
-from dulwich.objects import S_ISGITLINK, Blob, Commit, Tag, Tree
-from dulwich.pack import (Pack, PackData, PackIndexer, PackStreamCopier,
-                          _compute_object_size, compute_file_sha, iter_sha1,
-                          load_pack_index_file, read_pack_header,
-                          unpack_object, write_pack_header,
-                          write_pack_index_v2, write_pack_object)
-from dulwich.protocol import TCP_GIT_PORT
-from dulwich.refs import InfoRefsContainer, read_info_refs, write_info_refs
-from dulwich.repo import OBJECTDIR, BaseRepo
-from dulwich.server import Backend, TCPGitServer
+from ..greenthreads import GreenThreadsMissingObjectFinder
+from ..lru_cache import LRUSizeCache
+from ..object_store import INFODIR, PACKDIR, PackBasedObjectStore
+from ..objects import S_ISGITLINK, Blob, Commit, Tag, Tree
+from ..pack import (Pack, PackData, PackIndexer, PackStreamCopier,
+                    _compute_object_size, compute_file_sha, iter_sha1,
+                    load_pack_index_file, read_pack_header, unpack_object,
+                    write_pack_header, write_pack_index_v2, write_pack_object)
+from ..protocol import TCP_GIT_PORT
+from ..refs import InfoRefsContainer, read_info_refs, write_info_refs
+from ..repo import OBJECTDIR, BaseRepo
+from ..server import Backend, TCPGitServer
 
 """
 # Configuration file sample
blob - bec712ffbab3abf209f2ee2b8e8f0db1b9d661e2
blob + 9f5b21cd20f29e407d32e92a8802845411f4f5fc
--- dulwich/contrib/test_paramiko_vendor.py
+++ dulwich/contrib/test_paramiko_vendor.py
@@ -32,7 +32,7 @@ except ImportError:
     has_paramiko = False
 else:
     has_paramiko = True
-    from dulwich.contrib.paramiko_vendor import ParamikoSSHVendor
+    from .paramiko_vendor import ParamikoSSHVendor
 
     class Server(paramiko.ServerInterface):
         """http://docs.paramiko.org/en/2.4/api/server.html"""
blob - 5cdb91ffce03ee078bc25400b4e154ff4338082f
blob + bff588287fd9dc2c57b10efff537945ebfc267f2
--- dulwich/contrib/test_release_robot.py
+++ dulwich/contrib/test_release_robot.py
@@ -28,9 +28,10 @@ import time
 import unittest
 
 from dulwich.contrib import release_robot
-from dulwich.repo import Repo
-from dulwich.tests.utils import make_commit, make_tag
 
+from ..repo import Repo
+from ..tests.utils import make_commit, make_tag
+
 BASEDIR = os.path.abspath(os.path.dirname(__file__))  # this directory
 
 
blob - a1bd2813ad5e848d28549b16134d9d0daddc8fa6
blob + afb1b5c7658e2c24093da578784dc4ba22d20464
--- dulwich/contrib/test_swift.py
+++ dulwich/contrib/test_swift.py
@@ -28,10 +28,11 @@ from io import BytesIO, StringIO
 from time import time
 from unittest import skipIf
 
-from dulwich.objects import Blob, Commit, Tag, Tree, parse_timezone
 from dulwich.tests import TestCase
-from dulwich.tests.test_object_store import ObjectStoreTests
 
+from ..objects import Blob, Commit, Tag, Tree, parse_timezone
+from ..tests.test_object_store import ObjectStoreTests
+
 missing_libs = []
 
 try:
blob - 683bb6c0b04d41602f0de1198baf22f44d14e62d
blob + ca7698af381ce69d9efc3acc41191e422b256425
--- dulwich/credentials.py
+++ dulwich/credentials.py
@@ -28,7 +28,7 @@ import sys
 from typing import Iterator, Optional
 from urllib.parse import ParseResult, urlparse
 
-from dulwich.config import ConfigDict, SectionLike
+from .config import ConfigDict, SectionLike
 
 
 def match_urls(url: ParseResult, url_prefix: ParseResult) -> bool:
blob - 6ba691b59e601f082022e4a3280a055b94ed35a2
blob + a182fae3af7eb8489e14e0053129824c7af158b5
--- dulwich/diff_tree.py
+++ dulwich/diff_tree.py
@@ -26,7 +26,7 @@ from io import BytesIO
 from itertools import chain
 from typing import Dict, List, Optional
 
-from dulwich.objects import S_ISGITLINK, Tree, TreeEntry
+from .objects import S_ISGITLINK, Tree, TreeEntry
 
 # TreeChange type constants.
 CHANGE_ADD = "add"
blob - 7c16b3ea6b681aa4396cd4dcfaddd593cc6eb43b
blob + 335a0b8be23b3ea70174a00d1ec6f7bb20a667cf
--- dulwich/fastexport.py
+++ dulwich/fastexport.py
@@ -27,9 +27,9 @@ from fastimport import commands
 from fastimport import errors as fastimport_errors
 from fastimport import parser, processor
 
-from dulwich.index import commit_tree
-from dulwich.object_store import iter_tree_contents
-from dulwich.objects import ZERO_SHA, Blob, Commit, Tag
+from .index import commit_tree
+from .object_store import iter_tree_contents
+from .objects import ZERO_SHA, Blob, Commit, Tag
 
 
 def split_email(text):
blob - e416df7a289b69fb12f631168deb92e50ac23217
blob + 12a3048672ff66b8c51ea4860e73dfef4b90cf24
--- dulwich/greenthreads.py
+++ dulwich/greenthreads.py
@@ -25,9 +25,9 @@
 import gevent
 from gevent import pool
 
-from dulwich.object_store import (MissingObjectFinder, _collect_ancestors,
-                                  _collect_filetree_revs)
-from dulwich.objects import Commit, Tag
+from .object_store import (MissingObjectFinder, _collect_ancestors,
+                           _collect_filetree_revs)
+from .objects import Commit, Tag
 
 
 def _split_commits_and_tags(obj_store, lst, *, ignore_unknown=False, pool=None):
blob - 5ceffc4230f4389d054b772c8ec89939573fb4ec
blob + 9f00e50690419998128e06b9e341423cc0a2e029
--- dulwich/hooks.py
+++ dulwich/hooks.py
@@ -23,7 +23,7 @@
 import os
 import subprocess
 
-from dulwich.errors import HookError
+from .errors import HookError
 
 
 class Hook:
blob - bd60a70feb1086b00451b57fb191f98974a0ac51
blob + 352b2e64a987c5d28e494926b2a3468a99f0e251
--- dulwich/ignore.py
+++ dulwich/ignore.py
@@ -22,16 +22,16 @@
 For details for the matching rules, see https://git-scm.com/docs/gitignore
 """
 
-from contextlib import suppress
 import os.path
 import re
+from contextlib import suppress
 from typing import (TYPE_CHECKING, BinaryIO, Dict, Iterable, List, Optional,
                     Union)
 
 if TYPE_CHECKING:
-    from dulwich.repo import Repo
+    from .repo import Repo
 
-from dulwich.config import Config, get_xdg_config_home_path
+from .config import Config, get_xdg_config_home_path
 
 
 def _translate_segment(segment: bytes) -> bytes:
blob - bfd7da39a6eada661c7a6843f9706c06d1bb622a
blob + 672d6b67ca5c48dad654c60fe5faaf7aebd1a8f5
--- dulwich/index.py
+++ dulwich/index.py
@@ -28,11 +28,11 @@ import sys
 from typing import (Any, BinaryIO, Callable, Dict, Iterable, Iterator, List,
                     Optional, Tuple, Union)
 
-from dulwich.file import GitFile
-from dulwich.object_store import iter_tree_contents
-from dulwich.objects import (S_IFGITLINK, S_ISGITLINK, Blob, ObjectID, Tree,
-                             hex_to_sha, sha_to_hex)
-from dulwich.pack import ObjectContainer, SHA1Reader, SHA1Writer
+from .file import GitFile
+from .object_store import iter_tree_contents
+from .objects import (S_IFGITLINK, S_ISGITLINK, Blob, ObjectID, Tree,
+                      hex_to_sha, sha_to_hex)
+from .pack import ObjectContainer, SHA1Reader, SHA1Writer
 
 # TODO(jelmer): Switch to dataclass?
 IndexEntry = collections.namedtuple(
@@ -774,8 +774,8 @@ def read_submodule_head(path: Union[str, bytes]) -> Op
       path: path to the submodule
     Returns: HEAD sha, None if not a valid head/repository
     """
-    from dulwich.errors import NotGitRepository
-    from dulwich.repo import Repo
+    from .errors import NotGitRepository
+    from .repo import Repo
 
     # Repo currently expects a "str", so decode if necessary.
     # TODO(jelmer): Perhaps move this into Repo() ?
blob - 44a028dfd1c096769c1965e49fb8cca8f246cfdb
blob + e30bf480ed1e6a6f06b9102cd29ce38ff9ed850d
--- dulwich/line_ending.py
+++ dulwich/line_ending.py
@@ -136,9 +136,9 @@ Sources:
 - https://adaptivepatchwork.com/2012/03/01/mind-the-end-of-your-line/
 """
 
-from dulwich.object_store import iter_tree_contents
-from dulwich.objects import Blob
-from dulwich.patch import is_binary
+from .object_store import iter_tree_contents
+from .objects import Blob
+from .patch import is_binary
 
 CRLF = b"\r\n"
 LF = b"\n"
blob - 4446c75932bed0a4940a1c23faeb9468ff51b542
blob + d6eec790cb12d9c01141db07a039598c0c388e65
--- dulwich/object_store.py
+++ dulwich/object_store.py
@@ -36,22 +36,19 @@ try:
 except ImportError:  # python << 3.8
     from typing_extensions import Protocol  # type: ignore
 
-from dulwich.errors import NotTreeError
-from dulwich.file import GitFile
-from dulwich.objects import (S_ISGITLINK, ZERO_SHA, Blob, Commit, ObjectID,
-                             ShaFile, Tag, Tree, TreeEntry, hex_to_filename,
-                             hex_to_sha, object_class, sha_to_hex,
-                             valid_hexsha)
-from dulwich.pack import (PACK_SPOOL_FILE_MAX_SIZE, ObjectContainer, Pack,
-                          PackData, PackedObjectContainer, PackFileDisappeared,
-                          PackHint, PackIndexer, PackInflater,
-                          PackStreamCopier, UnpackedObject, extend_pack,
-                          full_unpacked_object, generate_unpacked_objects,
-                          iter_sha1, load_pack_index_file,
-                          pack_objects_to_data, write_pack_data,
-                          write_pack_index)
-from dulwich.protocol import DEPTH_INFINITE
-from dulwich.refs import PEELED_TAG_SUFFIX, Ref
+from .errors import NotTreeError
+from .file import GitFile
+from .objects import (S_ISGITLINK, ZERO_SHA, Blob, Commit, ObjectID, ShaFile,
+                      Tag, Tree, TreeEntry, hex_to_filename, hex_to_sha,
+                      object_class, sha_to_hex, valid_hexsha)
+from .pack import (PACK_SPOOL_FILE_MAX_SIZE, ObjectContainer, Pack, PackData,
+                   PackedObjectContainer, PackFileDisappeared, PackHint,
+                   PackIndexer, PackInflater, PackStreamCopier, UnpackedObject,
+                   extend_pack, full_unpacked_object,
+                   generate_unpacked_objects, iter_sha1, load_pack_index_file,
+                   pack_objects_to_data, write_pack_data, write_pack_index)
+from .protocol import DEPTH_INFINITE
+from .refs import PEELED_TAG_SUFFIX, Ref
 
 INFODIR = "info"
 PACKDIR = "pack"
@@ -161,7 +158,7 @@ class BaseObjectStore:
             (oldpath, newpath), (oldmode, newmode), (oldsha, newsha)
         """
 
-        from dulwich.diff_tree import tree_changes
+        from .diff_tree import tree_changes
         for change in tree_changes(
             self,
             source,
blob - 3da419739f842a0eb30c491438864ac228e6df17
blob + 3f4b52a63549fd480df813fe0e499fc9822a62c0
--- dulwich/objects.py
+++ dulwich/objects.py
@@ -25,29 +25,20 @@ import binascii
 import os
 import posixpath
 import stat
-from typing import (
-    Optional,
-    Dict,
-    Iterable,
-    Iterator,
-    List,
-    Tuple,
-    Type,
-    Union,
-    BinaryIO,
-)
+import warnings
 import zlib
 from collections import namedtuple
 from hashlib import sha1
 from io import BytesIO
-import warnings
+from typing import (BinaryIO, Dict, Iterable, Iterator, List, Optional, Tuple,
+                    Type, Union)
 
 from _hashlib import HASH
 
-from dulwich.errors import (ChecksumMismatch, FileFormatException,
-                            NotBlobError, NotCommitError, NotTagError,
-                            NotTreeError, ObjectFormatException)
-from dulwich.file import GitFile
+from .errors import (ChecksumMismatch, FileFormatException, NotBlobError,
+                     NotCommitError, NotTagError, NotTreeError,
+                     ObjectFormatException)
+from .file import GitFile
 
 ZERO_SHA = b"0" * 40
 
blob - 3435dcdb20838dfe9a2a44f51691c33357fe5588
blob + 22a759bbac3237ef56f4c6040c7a54cb3f575212
--- dulwich/objectspec.py
+++ dulwich/objectspec.py
@@ -20,12 +20,12 @@
 
 """Object specification."""
 
-from typing import List, Tuple, Union, TYPE_CHECKING, Optional, Iterator
+from typing import TYPE_CHECKING, Iterator, List, Optional, Tuple, Union
 
 if TYPE_CHECKING:
-    from dulwich.objects import ShaFile, Commit, Tree
-    from dulwich.refs import RefsContainer, Ref
-    from dulwich.repo import Repo
+    from .objects import Commit, ShaFile, Tree
+    from .refs import Ref, RefsContainer
+    from .repo import Repo
 
 
 def to_bytes(text: Union[str, bytes]) -> bytes:
blob - 4cba73f2379e218a661d6c77923b751b2f9b3a2b
blob + 0e9bf8a58acaeefbf46fcc696dba3673335e4791
--- dulwich/pack.py
+++ dulwich/pack.py
@@ -72,11 +72,10 @@ else:
 if sys.platform == "Plan9":
     has_mmap = False
 
-from dulwich.errors import ApplyDeltaError, ChecksumMismatch
-from dulwich.file import GitFile
-from dulwich.lru_cache import LRUSizeCache
-from dulwich.objects import (ObjectID, ShaFile, hex_to_sha, object_header,
-                             sha_to_hex)
+from .errors import ApplyDeltaError, ChecksumMismatch
+from .file import GitFile
+from .lru_cache import LRUSizeCache
+from .objects import ObjectID, ShaFile, hex_to_sha, object_header, sha_to_hex
 
 OFS_DELTA = 6
 REF_DELTA = 7
@@ -2593,7 +2592,7 @@ def extend_pack(f: BinaryIO, object_ids: Set[ObjectID]
 
 
 try:
-    from dulwich._pack import (apply_delta,  # type: ignore # noqa: F811
-                               bisect_find_sha)
+    from dulwich._pack import apply_delta  # type: ignore # noqa: F811
+    from dulwich._pack import bisect_find_sha  # type: ignore # noqa: F811
 except ImportError:
     pass
blob - 37555616de107718f1c1c5ac6343ca4015480f55
blob + ffdfdc3cf4b45b2a3fb6718812b0eed669c91b99
--- dulwich/patch.py
+++ dulwich/patch.py
@@ -29,8 +29,8 @@ import time
 from difflib import SequenceMatcher
 from typing import BinaryIO, Optional, TextIO, Union
 
-from dulwich.objects import S_ISGITLINK, Blob, Commit
-from dulwich.pack import ObjectContainer
+from .objects import S_ISGITLINK, Blob, Commit
+from .pack import ObjectContainer
 
 FIRST_FEW_BYTES = 8000
 
blob - cb8a6ce6c033d4860a84cec899ccbc6756b61aa5
blob + 8d15cc8f255770cde66c029122e1e80b37e2bd3f
--- dulwich/porcelain.py
+++ dulwich/porcelain.py
@@ -75,32 +75,32 @@ from io import BytesIO, RawIOBase
 from pathlib import Path
 from typing import Optional, Tuple, Union
 
-from dulwich.archive import tar_stream
-from dulwich.client import get_transport_and_path
-from dulwich.config import Config, ConfigFile, StackedConfig, read_submodules
-from dulwich.diff_tree import (CHANGE_ADD, CHANGE_COPY, CHANGE_DELETE,
-                               CHANGE_MODIFY, CHANGE_RENAME,
-                               RENAME_CHANGE_TYPES)
-from dulwich.errors import SendPackError
-from dulwich.file import ensure_dir_exists
-from dulwich.graph import can_fast_forward
-from dulwich.ignore import IgnoreFilterManager
-from dulwich.index import (_fs_to_tree_path, blob_from_path_and_stat,
-                           build_file_from_blob, get_unstaged_changes, index_entry_from_stat)
-from dulwich.object_store import tree_lookup_path, iter_tree_contents
-from dulwich.objects import (Commit, Tag, format_timezone, parse_timezone,
-                             pretty_format_tree_entry)
-from dulwich.objectspec import (parse_commit, parse_object, parse_ref,
-                                parse_reftuples, parse_tree, to_bytes)
-from dulwich.pack import write_pack_from_container, write_pack_index
-from dulwich.patch import write_tree_diff
-from dulwich.protocol import ZERO_SHA, Protocol
-from dulwich.refs import (LOCAL_BRANCH_PREFIX, LOCAL_REMOTE_PREFIX,
-                          LOCAL_TAG_PREFIX, _import_remote_refs)
-from dulwich.repo import BaseRepo, Repo
-from dulwich.server import (FileSystemBackend, ReceivePackHandler,
-                            TCPGitServer, UploadPackHandler)
-from dulwich.server import update_server_info as server_update_server_info
+from .archive import tar_stream
+from .client import get_transport_and_path
+from .config import Config, ConfigFile, StackedConfig, read_submodules
+from .diff_tree import (CHANGE_ADD, CHANGE_COPY, CHANGE_DELETE, CHANGE_MODIFY,
+                        CHANGE_RENAME, RENAME_CHANGE_TYPES)
+from .errors import SendPackError
+from .file import ensure_dir_exists
+from .graph import can_fast_forward
+from .ignore import IgnoreFilterManager
+from .index import (_fs_to_tree_path, blob_from_path_and_stat,
+                    build_file_from_blob, get_unstaged_changes,
+                    index_entry_from_stat)
+from .object_store import iter_tree_contents, tree_lookup_path
+from .objects import (Commit, Tag, format_timezone, parse_timezone,
+                      pretty_format_tree_entry)
+from .objectspec import (parse_commit, parse_object, parse_ref,
+                         parse_reftuples, parse_tree, to_bytes)
+from .pack import write_pack_from_container, write_pack_index
+from .patch import write_tree_diff
+from .protocol import ZERO_SHA, Protocol
+from .refs import (LOCAL_BRANCH_PREFIX, LOCAL_REMOTE_PREFIX, LOCAL_TAG_PREFIX,
+                   _import_remote_refs)
+from .repo import BaseRepo, Repo
+from .server import (FileSystemBackend, ReceivePackHandler, TCPGitServer,
+                     UploadPackHandler)
+from .server import update_server_info as server_update_server_info
 
 # Module level tuple definition for status output
 GitStatus = namedtuple("GitStatus", "staged unstaged untracked")
@@ -1461,8 +1461,8 @@ def web_daemon(path=".", address=None, port=None):
       address: Optional address to listen on (defaults to ::)
       port: Optional port to listen on (defaults to 80)
     """
-    from dulwich.web import (WSGIRequestHandlerLogger, WSGIServerLogger,
-                             make_server, make_wsgi_chain)
+    from .web import (WSGIRequestHandlerLogger, WSGIServerLogger, make_server,
+                      make_wsgi_chain)
 
     backend = FileSystemBackend(path)
     app = make_wsgi_chain(backend)
@@ -1974,7 +1974,7 @@ def check_mailmap(repo, contact):
     Returns: Canonical contact data
     """
     with open_repo_closing(repo) as r:
-        from dulwich.mailmap import Mailmap
+        from .mailmap import Mailmap
 
         try:
             mailmap = Mailmap.from_path(os.path.join(r.path, ".mailmap"))
@@ -2005,7 +2005,7 @@ def fsck(repo):
 def stash_list(repo):
     """List all stashes in a repository."""
     with open_repo_closing(repo) as r:
-        from dulwich.stash import Stash
+        from .stash import Stash
 
         stash = Stash.from_repo(r)
         return enumerate(list(stash.stashes()))
@@ -2014,7 +2014,7 @@ def stash_list(repo):
 def stash_push(repo):
     """Push a new stash onto the stack."""
     with open_repo_closing(repo) as r:
-        from dulwich.stash import Stash
+        from .stash import Stash
 
         stash = Stash.from_repo(r)
         stash.push()
@@ -2023,7 +2023,7 @@ def stash_push(repo):
 def stash_pop(repo, index):
     """Pop a stash from the stack."""
     with open_repo_closing(repo) as r:
-        from dulwich.stash import Stash
+        from .stash import Stash
 
         stash = Stash.from_repo(r)
         stash.pop(index)
@@ -2032,7 +2032,7 @@ def stash_pop(repo, index):
 def stash_drop(repo, index):
     """Drop a stash from the stack."""
     with open_repo_closing(repo) as r:
-        from dulwich.stash import Stash
+        from .stash import Stash
 
         stash = Stash.from_repo(r)
         stash.drop(index)
blob - b08cb14285c5509954f0dafda86521364ef37ec9
blob + f3cdcd8f9a0d15dd0e9e0e2c9da3ff86ac7bfedd
--- dulwich/protocol.py
+++ dulwich/protocol.py
@@ -25,8 +25,9 @@ from io import BytesIO
 from os import SEEK_END
 
 import dulwich
-from dulwich.errors import GitProtocolError, HangupException
 
+from .errors import GitProtocolError, HangupException
+
 TCP_GIT_PORT = 9418
 
 ZERO_SHA = b"0" * 40
blob - edab42b7aa96cecf5ccd5f3493de76d3fceee3b9
blob + 2be241c9892147968a29638dedfbe3fe7037bbea
--- dulwich/reflog.py
+++ dulwich/reflog.py
@@ -23,7 +23,7 @@
 
 import collections
 
-from dulwich.objects import ZERO_SHA, format_timezone, parse_timezone
+from .objects import ZERO_SHA, format_timezone, parse_timezone
 
 Entry = collections.namedtuple(
     "Entry",
blob - fe47dc7dbd8ce9c3e81fc689ac4a35dc4ebbe72f
blob + 9f6f70de42d4f0fc4f9ec5c2c4eb8b44e47150d2
--- dulwich/refs.py
+++ dulwich/refs.py
@@ -27,10 +27,10 @@ import warnings
 from contextlib import suppress
 from typing import Dict, Optional
 
-from dulwich.errors import PackedRefsException, RefFormatError
-from dulwich.file import GitFile, ensure_dir_exists
-from dulwich.objects import ZERO_SHA, ObjectID, Tag, git_line, valid_hexsha
-from dulwich.pack import ObjectContainer
+from .errors import PackedRefsException, RefFormatError
+from .file import GitFile, ensure_dir_exists
+from .objects import ZERO_SHA, ObjectID, Tag, git_line, valid_hexsha
+from .pack import ObjectContainer
 
 Ref = bytes
 
@@ -1145,7 +1145,7 @@ def read_info_refs(f):
 def write_info_refs(refs, store: ObjectContainer):
     """Generate info refs."""
     # TODO: Avoid recursive import :(
-    from dulwich.object_store import peel_sha
+    from .object_store import peel_sha
     for name, sha in sorted(refs.items()):
         # get_refs() includes HEAD as a special case, but we don't want to
         # advertise it
@@ -1273,7 +1273,7 @@ def _import_remote_refs(
 
 def serialize_refs(store, refs):
     # TODO: Avoid recursive import :(
-    from dulwich.object_store import peel_sha
+    from .object_store import peel_sha
     ret = {}
     for ref, sha in refs.items():
         try:
blob - a64b496fe81447b9a5fdfb50c6bd7e04ea7839f2
blob + 4450dce43695532c0763f0c266909ca0a185f966
--- dulwich/repo.py
+++ dulwich/repo.py
@@ -41,30 +41,29 @@ if TYPE_CHECKING:
     # There are no circular imports here, but we try to defer imports as long
     # as possible to reduce start-up time for anything that doesn't need
     # these imports.
-    from dulwich.config import StackedConfig, ConfigFile
-    from dulwich.index import Index
+    from .config import StackedConfig, ConfigFile
+    from .index import Index
 
-from dulwich.errors import (CommitError, HookError, NoIndexPresent,
-                            NotBlobError, NotCommitError, NotGitRepository,
-                            NotTagError, NotTreeError, RefFormatError)
-from dulwich.file import GitFile
-from dulwich.hooks import (CommitMsgShellHook, Hook, PostCommitShellHook,
-                           PostReceiveShellHook, PreCommitShellHook)
-from dulwich.line_ending import BlobNormalizer, TreeBlobNormalizer
-from dulwich.object_store import (DiskObjectStore, MemoryObjectStore,
-                                  MissingObjectFinder, ObjectStoreGraphWalker,
-                                  PackBasedObjectStore, peel_sha)
-from dulwich.objects import (Blob, Commit, ObjectID, ShaFile, Tag, Tree,
-                             check_hexsha, valid_hexsha)
-from dulwich.pack import generate_unpacked_objects
-from dulwich.refs import (ANNOTATED_TAG_SUFFIX,  # noqa: F401
-                          LOCAL_BRANCH_PREFIX, LOCAL_TAG_PREFIX, SYMREF,
-                          DictRefsContainer, DiskRefsContainer,
-                          InfoRefsContainer, Ref, RefsContainer,
-                          _set_default_branch, _set_head, _set_origin_head,
-                          check_ref_format, read_packed_refs,
-                          read_packed_refs_with_peeled, serialize_refs,
-                          write_packed_refs)
+from .errors import (CommitError, HookError, NoIndexPresent, NotBlobError,
+                     NotCommitError, NotGitRepository, NotTagError,
+                     NotTreeError, RefFormatError)
+from .file import GitFile
+from .hooks import (CommitMsgShellHook, Hook, PostCommitShellHook,
+                    PostReceiveShellHook, PreCommitShellHook)
+from .line_ending import BlobNormalizer, TreeBlobNormalizer
+from .object_store import (DiskObjectStore, MemoryObjectStore,
+                           MissingObjectFinder, ObjectStoreGraphWalker,
+                           PackBasedObjectStore, peel_sha)
+from .objects import (Blob, Commit, ObjectID, ShaFile, Tag, Tree, check_hexsha,
+                      valid_hexsha)
+from .pack import generate_unpacked_objects
+from .refs import (ANNOTATED_TAG_SUFFIX, LOCAL_BRANCH_PREFIX,  # noqa: F401
+                   LOCAL_TAG_PREFIX, SYMREF,
+                   DictRefsContainer, DiskRefsContainer, InfoRefsContainer,
+                   Ref, RefsContainer, _set_default_branch, _set_head,
+                   _set_origin_head, check_ref_format, read_packed_refs,
+                   read_packed_refs_with_peeled, serialize_refs,
+                   write_packed_refs)
 
 CONTROLDIR = ".git"
 OBJECTDIR = "objects"
@@ -331,7 +330,7 @@ class BaseRepo:
 
     def _init_files(self, bare: bool) -> None:
         """Initialize a default set of named files."""
-        from dulwich.config import ConfigFile
+        from .config import ConfigFile
 
         self._put_named_file("description", b"Unnamed repository")
         f = BytesIO()
@@ -659,7 +658,7 @@ class BaseRepo:
 
         Returns: `Config` instance for this repository
         """
-        from dulwich.config import ConfigFile, StackedConfig
+        from .config import ConfigFile, StackedConfig
 
         local_config = self.get_config()
         backends: List[ConfigFile] = [local_config]
@@ -740,7 +739,7 @@ class BaseRepo:
             Walker.
         Returns: A `Walker` object
         """
-        from dulwich.walk import Walker
+        from .walk import Walker
 
         if include is None:
             include = [self.head()]
@@ -1286,7 +1285,7 @@ class Repo(BaseRepo):
           NoIndexPresent: If no index is present
         Returns: The matching `Index`
         """
-        from dulwich.index import Index
+        from .index import Index
 
         if not self.has_index():
             raise NoIndexPresent()
@@ -1311,9 +1310,8 @@ class Repo(BaseRepo):
             fs_paths = [fs_paths]
         fs_paths = list(fs_paths)
 
-        from dulwich.index import (_fs_to_tree_path, blob_from_path_and_stat,
-                                   index_entry_from_directory,
-                                   index_entry_from_stat)
+        from .index import (_fs_to_tree_path, blob_from_path_and_stat,
+                            index_entry_from_directory, index_entry_from_stat)
 
         index = self.open_index()
         blob_normalizer = self.get_blob_normalizer()
@@ -1363,7 +1361,7 @@ class Repo(BaseRepo):
           fs_paths: a list of files to unstage,
             relative to the repository path
         """
-        from dulwich.index import IndexEntry, _fs_to_tree_path
+        from .index import IndexEntry, _fs_to_tree_path
 
         index = self.open_index()
         try:
@@ -1514,9 +1512,9 @@ class Repo(BaseRepo):
         Args:
           tree: Tree SHA to reset to, None for current HEAD tree.
         """
-        from dulwich.index import (build_index_from_tree,
-                                   validate_path_element_default,
-                                   validate_path_element_ntfs)
+        from .index import (build_index_from_tree,
+                            validate_path_element_default,
+                            validate_path_element_ntfs)
 
         if tree is None:
             head = self[b"HEAD"]
@@ -1541,7 +1539,7 @@ class Repo(BaseRepo):
         )
 
     def get_worktree_config(self) -> "ConfigFile":
-        from dulwich.config import ConfigFile
+        from .config import ConfigFile
         path = os.path.join(self.commondir(), "config.worktree")
         try:
             return ConfigFile.from_path(path)
@@ -1555,7 +1553,7 @@ class Repo(BaseRepo):
 
         Returns: `ConfigFile` object for the ``.git/config`` file.
         """
-        from dulwich.config import ConfigFile
+        from .config import ConfigFile
 
         path = os.path.join(self._commondir, "config")
         try:
@@ -1600,7 +1598,7 @@ class Repo(BaseRepo):
         ret = cls(path, bare=bare, object_store=object_store)
         if default_branch is None:
             if config is None:
-                from dulwich.config import StackedConfig
+                from .config import StackedConfig
                 config = StackedConfig.default()
             try:
                 default_branch = config.get("init", "defaultBranch")
@@ -1717,7 +1715,7 @@ class MemoryRepo(BaseRepo):
     """
 
     def __init__(self):
-        from dulwich.config import ConfigFile
+        from .config import ConfigFile
 
         self._reflog = []
         refs_container = DictRefsContainer({}, logger=self._append_reflog)
blob - 8831e16b98652b5f86e2eb94f2d4be432aa0e2b7
blob + 8d980d71eab326d1b67da5711df58f2a7a140106
--- dulwich/server.py
+++ dulwich/server.py
@@ -59,36 +59,35 @@ import socketserver
 import zlib
 
 from dulwich import log_utils
-from dulwich.archive import tar_stream
-from dulwich.errors import (ApplyDeltaError, ChecksumMismatch,
-                            GitProtocolError, HookError, NotGitRepository,
-                            ObjectFormatException, UnexpectedCommandError)
-from dulwich.object_store import peel_sha
-from dulwich.objects import Commit, ObjectID, valid_hexsha
-from dulwich.pack import (ObjectContainer, PackedObjectContainer,
-                          write_pack_from_container)
-from dulwich.protocol import (CAPABILITIES_REF, CAPABILITY_AGENT,
-                              CAPABILITY_DELETE_REFS, CAPABILITY_INCLUDE_TAG,
-                              CAPABILITY_MULTI_ACK,
-                              CAPABILITY_MULTI_ACK_DETAILED,
-                              CAPABILITY_NO_DONE, CAPABILITY_NO_PROGRESS,
-                              CAPABILITY_OFS_DELTA, CAPABILITY_QUIET,
-                              CAPABILITY_REPORT_STATUS, CAPABILITY_SHALLOW,
-                              CAPABILITY_SIDE_BAND_64K, CAPABILITY_THIN_PACK,
-                              COMMAND_DEEPEN, COMMAND_DONE, COMMAND_HAVE,
-                              COMMAND_SHALLOW, COMMAND_UNSHALLOW, COMMAND_WANT,
-                              MULTI_ACK, MULTI_ACK_DETAILED, NAK_LINE,
-                              SIDE_BAND_CHANNEL_DATA, SIDE_BAND_CHANNEL_FATAL,
-                              SIDE_BAND_CHANNEL_PROGRESS, SINGLE_ACK,
-                              TCP_GIT_PORT, ZERO_SHA, BufferedPktLineWriter,
-                              Protocol, ReceivableProtocol, ack_type,
-                              capability_agent, extract_capabilities,
-                              extract_want_line_capabilities, format_ack_line,
-                              format_ref_line, format_shallow_line,
-                              format_unshallow_line, symref_capabilities)
-from dulwich.refs import PEELED_TAG_SUFFIX, RefsContainer, write_info_refs
-from dulwich.repo import BaseRepo, Repo
 
+from .archive import tar_stream
+from .errors import (ApplyDeltaError, ChecksumMismatch, GitProtocolError,
+                     HookError, NotGitRepository, ObjectFormatException,
+                     UnexpectedCommandError)
+from .object_store import peel_sha
+from .objects import Commit, ObjectID, valid_hexsha
+from .pack import (ObjectContainer, PackedObjectContainer,
+                   write_pack_from_container)
+from .protocol import (CAPABILITIES_REF, CAPABILITY_AGENT,
+                       CAPABILITY_DELETE_REFS, CAPABILITY_INCLUDE_TAG,
+                       CAPABILITY_MULTI_ACK, CAPABILITY_MULTI_ACK_DETAILED,
+                       CAPABILITY_NO_DONE, CAPABILITY_NO_PROGRESS,
+                       CAPABILITY_OFS_DELTA, CAPABILITY_QUIET,
+                       CAPABILITY_REPORT_STATUS, CAPABILITY_SHALLOW,
+                       CAPABILITY_SIDE_BAND_64K, CAPABILITY_THIN_PACK,
+                       COMMAND_DEEPEN, COMMAND_DONE, COMMAND_HAVE,
+                       COMMAND_SHALLOW, COMMAND_UNSHALLOW, COMMAND_WANT,
+                       MULTI_ACK, MULTI_ACK_DETAILED, NAK_LINE,
+                       SIDE_BAND_CHANNEL_DATA, SIDE_BAND_CHANNEL_FATAL,
+                       SIDE_BAND_CHANNEL_PROGRESS, SINGLE_ACK, TCP_GIT_PORT,
+                       ZERO_SHA, BufferedPktLineWriter, Protocol,
+                       ReceivableProtocol, ack_type, capability_agent,
+                       extract_capabilities, extract_want_line_capabilities,
+                       format_ack_line, format_ref_line, format_shallow_line,
+                       format_unshallow_line, symref_capabilities)
+from .refs import PEELED_TAG_SUFFIX, RefsContainer, write_info_refs
+from .repo import BaseRepo, Repo
+
 logger = log_utils.getLogger(__name__)
 
 
blob - e0d5af799a514d6454f59cb6a1455a78c0757a09
blob + fb8d824f6e2be5473b6c1867a754d2e4538bc365
--- dulwich/stash.py
+++ dulwich/stash.py
@@ -23,9 +23,9 @@
 
 import os
 
-from dulwich.file import GitFile
-from dulwich.index import commit_tree, iter_fresh_objects
-from dulwich.reflog import drop_reflog_entry, read_reflog
+from .file import GitFile
+from .index import commit_tree, iter_fresh_objects
+from .reflog import drop_reflog_entry, read_reflog
 
 DEFAULT_STASH_REF = b"refs/stash"
 
blob - a7eb9576771665337751c93f5a65f35b8c36deec
blob + abc677726b4c8cc0e92c29df75dd7646a2b5ce17
--- dulwich/tests/compat/server_utils.py
+++ dulwich/tests/compat/server_utils.py
@@ -26,12 +26,12 @@ import shutil
 import socket
 import tempfile
 
-from dulwich.objects import hex_to_sha
-from dulwich.protocol import CAPABILITY_SIDE_BAND_64K
-from dulwich.repo import Repo
-from dulwich.server import ReceivePackHandler
-from dulwich.tests.compat.utils import require_git_version, run_git_or_fail
-from dulwich.tests.utils import tear_down_repo
+from ...objects import hex_to_sha
+from ...protocol import CAPABILITY_SIDE_BAND_64K
+from ...repo import Repo
+from ...server import ReceivePackHandler
+from ..utils import tear_down_repo
+from .utils import require_git_version, run_git_or_fail
 
 
 class _StubRepo:
blob - 15ed1dadb225cf581fc7f385dc61dc3d2bd4116b
blob + e811f7bf509547be60cb73c2d45ea5239360c4c1
--- dulwich/tests/compat/test_client.py
+++ dulwich/tests/compat/test_client.py
@@ -20,7 +20,6 @@
 
 """Compatibility tests between the Dulwich client and the cgit server."""
 
-from contextlib import suppress
 import copy
 import http.server
 import os
@@ -32,14 +31,15 @@ import sys
 import tarfile
 import tempfile
 import threading
+from contextlib import suppress
 from io import BytesIO
 from urllib.parse import unquote
 
 from dulwich import client, file, index, objects, protocol, repo
 from dulwich.tests import SkipTest, expectedFailure
-from dulwich.tests.compat.utils import (_DEFAULT_GIT, CompatTestCase,
-                                        check_for_daemon, import_repo_to_dir,
-                                        rmtree_ro, run_git_or_fail)
+
+from .utils import (_DEFAULT_GIT, CompatTestCase, check_for_daemon,
+                    import_repo_to_dir, rmtree_ro, run_git_or_fail)
 
 if sys.platform == "win32":
     import ctypes
blob - 040c4c327e6e420a315bda48f4aa9bf143f7291e
blob + 1bd9f55e7b0af1050019d1a825cdbe97be93c32e
--- dulwich/tests/compat/test_pack.py
+++ dulwich/tests/compat/test_pack.py
@@ -27,12 +27,13 @@ import re
 import shutil
 import tempfile
 
-from dulwich.objects import Blob
-from dulwich.pack import write_pack
 from dulwich.tests import SkipTest
-from dulwich.tests.compat.utils import require_git_version, run_git_or_fail
-from dulwich.tests.test_pack import PackTests, a_sha, pack1_sha
 
+from ...objects import Blob
+from ...pack import write_pack
+from ..test_pack import PackTests, a_sha, pack1_sha
+from .utils import require_git_version, run_git_or_fail
+
 _NON_DELTA_RE = re.compile(b"non delta: (?P<non_delta>\\d+) objects")
 
 
blob - aabda17cef2118213f2d83ebbe0c365772b62258
blob + 08c10e249fae375fce7c8905ecdd14c8c2c5cedd
--- dulwich/tests/compat/test_patch.py
+++ dulwich/tests/compat/test_patch.py
@@ -25,10 +25,11 @@ import tempfile
 from io import BytesIO
 
 from dulwich import porcelain
-from dulwich.repo import Repo
-from dulwich.tests.compat.utils import CompatTestCase, run_git_or_fail
 
+from ...repo import Repo
+from .utils import CompatTestCase, run_git_or_fail
 
+
 class CompatPatchTestCase(CompatTestCase):
     def setUp(self):
         super().setUp()
blob - 14c7fcf18312c25d0551c9f50782c71dd96c18ca
blob + 97e441612c8c3f05c919408b08913f305ef471dc
--- dulwich/tests/compat/test_porcelain.py
+++ dulwich/tests/compat/test_porcelain.py
@@ -26,11 +26,12 @@ import sys
 from unittest import skipIf
 
 from dulwich import porcelain
-from dulwich.tests.compat.utils import CompatTestCase, run_git_or_fail
-from dulwich.tests.test_porcelain import PorcelainGpgTestCase
-from dulwich.tests.utils import build_commit_graph
 
+from ..test_porcelain import PorcelainGpgTestCase
+from ..utils import build_commit_graph
+from .utils import CompatTestCase, run_git_or_fail
 
+
 @skipIf(platform.python_implementation() == "PyPy" or sys.platform == "win32", "gpgme not easily available or supported on Windows and PyPy")
 class TagCreateSignTestCase(PorcelainGpgTestCase, CompatTestCase):
     def setUp(self):
blob - c0191e0f9a547660a602592213ab0532b3b57e3b
blob + fac2c1c7707cd3c29296b51543e98afd7be4b678
--- dulwich/tests/compat/test_repository.py
+++ dulwich/tests/compat/test_repository.py
@@ -26,10 +26,10 @@ import tempfile
 from io import BytesIO
 from itertools import chain
 
-from dulwich.objects import hex_to_sha
-from dulwich.repo import Repo, check_ref_format
-from dulwich.tests.compat.utils import (CompatTestCase, require_git_version,
-                                        rmtree_ro, run_git_or_fail)
+from ...objects import hex_to_sha
+from ...repo import Repo, check_ref_format
+from .utils import (CompatTestCase, require_git_version, rmtree_ro,
+                    run_git_or_fail)
 
 
 class ObjectStoreTestCase(CompatTestCase):
blob - 7fc5026db1f0e23c249d2d5fc3ddce48f34c6d46
blob + 238fb39342f76893e9fddcd2cd3d2bd14f625e92
--- dulwich/tests/compat/test_server.py
+++ dulwich/tests/compat/test_server.py
@@ -29,13 +29,13 @@ import os
 import sys
 import threading
 
-from dulwich.server import DictBackend, TCPGitServer
 from dulwich.tests import skipIf
-from dulwich.tests.compat.server_utils import (NoSideBand64kReceivePackHandler,
-                                               ServerTests)
-from dulwich.tests.compat.utils import CompatTestCase, require_git_version
 
+from ...server import DictBackend, TCPGitServer
+from .server_utils import NoSideBand64kReceivePackHandler, ServerTests
+from .utils import CompatTestCase, require_git_version
 
+
 @skipIf(sys.platform == "win32", "Broken on windows, with very long fail time.")
 class GitServerTestCase(ServerTests, CompatTestCase):
     """Tests for client/server compatibility.
blob - bf5754fb41c45cf1947531fd65ef7b7b94d3d7fd
blob + 4001ec27086740d5f2bbd20601927a2dfa736780
--- dulwich/tests/compat/test_web.py
+++ dulwich/tests/compat/test_web.py
@@ -30,15 +30,15 @@ import threading
 from typing import Tuple
 from wsgiref import simple_server
 
-from dulwich.server import DictBackend, ReceivePackHandler, UploadPackHandler
 from dulwich.tests import SkipTest, skipIf
-from dulwich.tests.compat.server_utils import (NoSideBand64kReceivePackHandler,
-                                               ServerTests)
-from dulwich.tests.compat.utils import CompatTestCase
-from dulwich.web import (HTTPGitApplication, WSGIRequestHandlerLogger,
-                         WSGIServerLogger, make_wsgi_chain)
 
+from ...server import DictBackend, ReceivePackHandler, UploadPackHandler
+from ...web import (HTTPGitApplication, WSGIRequestHandlerLogger,
+                    WSGIServerLogger, make_wsgi_chain)
+from .server_utils import NoSideBand64kReceivePackHandler, ServerTests
+from .utils import CompatTestCase
 
+
 @skipIf(sys.platform == "win32", "Broken on windows, with very long fail time.")
 class WebTests(ServerTests):
     """Base tests for web server tests.
blob - d823d2349e554cc40b195e51896d0c073b4980f2
blob + b6a13c69df79a2390bd5e961444d2854d9565846
--- dulwich/tests/compat/utils.py
+++ dulwich/tests/compat/utils.py
@@ -32,10 +32,11 @@ import tempfile
 import time
 from typing import Tuple
 
-from dulwich.protocol import TCP_GIT_PORT
-from dulwich.repo import Repo
 from dulwich.tests import SkipTest, TestCase
 
+from ...protocol import TCP_GIT_PORT
+from ...repo import Repo
+
 _DEFAULT_GIT = "git"
 _VERSION_LEN = 4
 _REPOS_DATA_DIR = os.path.abspath(
blob - bf188026b8c55e19f3b7445bbc30cecd65d3781f
blob + 0c84509df8083ee8dab1fb5584e30ad88b7d6865
--- dulwich/tests/test_archive.py
+++ dulwich/tests/test_archive.py
@@ -25,12 +25,13 @@ import tarfile
 from io import BytesIO
 from unittest import skipUnless
 
-from dulwich.archive import tar_stream
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Blob, Tree
 from dulwich.tests import TestCase
-from dulwich.tests.utils import build_commit_graph
 
+from ..archive import tar_stream
+from ..object_store import MemoryObjectStore
+from ..objects import Blob, Tree
+from .utils import build_commit_graph
+
 try:
     from unittest.mock import patch
 except ImportError:
blob - 82148488183c11edcf5e048d80f9b8e7fe3acb7d
blob + 7041ce00d3f1f8e41196e101e30b961b098ed8bc
--- dulwich/tests/test_blackbox.py
+++ dulwich/tests/test_blackbox.py
@@ -23,10 +23,11 @@
 import shutil
 import tempfile
 
-from dulwich.repo import Repo
 from dulwich.tests import BlackboxTestCase
 
+from ..repo import Repo
 
+
 class GitReceivePackTests(BlackboxTestCase):
     """Blackbox tests for dul-receive-pack."""
 
blob - 22c4d0efb59cc47b24af35471fe3bc8de3ccc05d
blob + 1f0cba2c810290317f29451eb7e9c9f0130ff1b6
--- dulwich/tests/test_bundle.py
+++ dulwich/tests/test_bundle.py
@@ -24,11 +24,12 @@ import os
 import tempfile
 from io import BytesIO
 
-from dulwich.bundle import Bundle, read_bundle, write_bundle
-from dulwich.pack import PackData, write_pack_objects
 from dulwich.tests import TestCase
 
+from ..bundle import Bundle, read_bundle, write_bundle
+from ..pack import PackData, write_pack_objects
 
+
 class BundleTests(TestCase):
     def test_roundtrip_bundle(self):
         origbundle = Bundle()
blob - fdb54b9a108b15c8a5cff9a8468bdd77ccbd129e
blob + 8886d44afe94a29188ac49859d8f8ca13c1ea131
--- dulwich/tests/test_client.py
+++ dulwich/tests/test_client.py
@@ -31,26 +31,25 @@ from urllib.parse import urlparse
 
 import dulwich
 from dulwich import client
-from dulwich.client import (FetchPackResult, GitProtocolError, HangupException,
-                            HttpGitClient, InvalidWants, LocalGitClient,
-                            PLinkSSHVendor, ReportStatusParser, SendPackError,
-                            SSHGitClient, StrangeHostname, SubprocessSSHVendor,
-                            TCPGitClient, TraditionalGitClient,
-                            _remote_error_from_stderr, check_wants,
-                            default_urllib3_manager,
-                            get_credentials_from_store, get_transport_and_path,
-                            get_transport_and_path_from_url, parse_rsync_url)
-from dulwich.config import ConfigDict
-from dulwich.objects import Commit, Tree
-from dulwich.pack import (pack_objects_to_data, write_pack_data,
-                          write_pack_objects)
-from dulwich.protocol import TCP_GIT_PORT, Protocol
-from dulwich.repo import MemoryRepo, Repo
 from dulwich.tests import TestCase, skipIf
-from dulwich.tests.utils import (open_repo, setup_warning_catcher,
-                                 tear_down_repo)
 
+from ..client import (FetchPackResult, GitProtocolError, HangupException,
+                      HttpGitClient, InvalidWants, LocalGitClient,
+                      PLinkSSHVendor, ReportStatusParser, SendPackError,
+                      SSHGitClient, StrangeHostname, SubprocessSSHVendor,
+                      TCPGitClient, TraditionalGitClient,
+                      _remote_error_from_stderr, check_wants,
+                      default_urllib3_manager, get_credentials_from_store,
+                      get_transport_and_path, get_transport_and_path_from_url,
+                      parse_rsync_url)
+from ..config import ConfigDict
+from ..objects import Commit, Tree
+from ..pack import pack_objects_to_data, write_pack_data, write_pack_objects
+from ..protocol import TCP_GIT_PORT, Protocol
+from ..repo import MemoryRepo, Repo
+from .utils import open_repo, setup_warning_catcher, tear_down_repo
 
+
 class DummyClient(TraditionalGitClient):
     def __init__(self, can_read, read, write):
         self.can_read = can_read
blob - ed49f38c550a0fa56c1a52ce5df3013a24452ff0
blob + 01a53427507b5a6782320d71d302da1134dafb00
--- dulwich/tests/test_config.py
+++ dulwich/tests/test_config.py
@@ -26,13 +26,14 @@ from io import BytesIO
 from unittest import skipIf
 from unittest.mock import patch
 
-from dulwich.config import (ConfigDict, ConfigFile, StackedConfig,
-                            _check_section_name, _check_variable_name,
-                            _escape_value, _format_string, _parse_string,
-                            apply_instead_of, parse_submodules)
 from dulwich.tests import TestCase
 
+from ..config import (ConfigDict, ConfigFile, StackedConfig,
+                      _check_section_name, _check_variable_name, _escape_value,
+                      _format_string, _parse_string, apply_instead_of,
+                      parse_submodules)
 
+
 class ConfigFileTests(TestCase):
     def from_file(self, text):
         return ConfigFile.from_file(BytesIO(text))
@@ -302,7 +303,7 @@ class StackedConfigTests(TestCase):
 
     @skipIf(sys.platform != "win32", "Windows specific config location.")
     def test_windows_config_from_path(self):
-        from dulwich.config import get_win_system_paths
+        from ..config import get_win_system_paths
 
         install_dir = os.path.join("C:", "foo", "Git")
         self.overrideEnv("PATH", os.path.join(install_dir, "cmd"))
@@ -320,7 +321,7 @@ class StackedConfigTests(TestCase):
     def test_windows_config_from_reg(self):
         import winreg
 
-        from dulwich.config import get_win_system_paths
+        from ..config import get_win_system_paths
 
         self.overrideEnv("PATH", None)
         install_dir = os.path.join("C:", "foo", "Git")
blob - 046f46bd59ad5f5395e0632dab2d79e93d1f4abc
blob + 7910900b5270fefd96d885f5e39878d2e4409636
--- dulwich/tests/test_credentials.py
+++ dulwich/tests/test_credentials.py
@@ -21,12 +21,13 @@
 
 from urllib.parse import urlparse
 
-from dulwich.config import ConfigDict
-from dulwich.credentials import (match_partial_url, match_urls,
-                                 urlmatch_credential_sections)
 from dulwich.tests import TestCase
 
+from ..config import ConfigDict
+from ..credentials import (match_partial_url, match_urls,
+                           urlmatch_credential_sections)
 
+
 class TestCredentialHelpersUtils(TestCase):
 
     def test_match_urls(self):
blob - 0be756f98a7c8036bb0c9038ec4d7ec726d137c3
blob + 16cdd7a748da29c02b45840320641be4c6cf94e7
--- dulwich/tests/test_diff_tree.py
+++ dulwich/tests/test_diff_tree.py
@@ -22,18 +22,18 @@
 
 from itertools import permutations
 
-from dulwich.diff_tree import (CHANGE_COPY, CHANGE_MODIFY, CHANGE_RENAME,
-                               CHANGE_UNCHANGED, RenameDetector, TreeChange,
-                               _count_blocks, _count_blocks_py, _is_tree,
-                               _is_tree_py, _merge_entries, _merge_entries_py,
-                               _similarity_score, _tree_change_key,
-                               tree_changes, tree_changes_for_merge)
-from dulwich.index import commit_tree
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Blob, ShaFile, Tree, TreeEntry
 from dulwich.tests import TestCase
-from dulwich.tests.utils import (F, ext_functest_builder, functest_builder,
-                                 make_object)
+
+from ..diff_tree import (CHANGE_COPY, CHANGE_MODIFY, CHANGE_RENAME,
+                         CHANGE_UNCHANGED, RenameDetector, TreeChange,
+                         _count_blocks, _count_blocks_py, _is_tree,
+                         _is_tree_py, _merge_entries, _merge_entries_py,
+                         _similarity_score, _tree_change_key, tree_changes,
+                         tree_changes_for_merge)
+from ..index import commit_tree
+from ..object_store import MemoryObjectStore
+from ..objects import Blob, ShaFile, Tree, TreeEntry
+from .utils import F, ext_functest_builder, functest_builder, make_object
 
 
 class DiffTestCase(TestCase):
blob - 644ddd4acd75952e9691b97913d6eee09346fdc4
blob + 9827234051e77a3729d99b90abb181e5d76b46d7
--- dulwich/tests/test_fastexport.py
+++ dulwich/tests/test_fastexport.py
@@ -21,13 +21,14 @@
 import stat
 from io import BytesIO
 
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import ZERO_SHA, Blob, Commit, Tree
-from dulwich.repo import MemoryRepo
 from dulwich.tests import SkipTest, TestCase
-from dulwich.tests.utils import build_commit_graph
 
+from ..object_store import MemoryObjectStore
+from ..objects import ZERO_SHA, Blob, Commit, Tree
+from ..repo import MemoryRepo
+from .utils import build_commit_graph
 
+
 class GitFastExporterTests(TestCase):
     """Tests for the GitFastExporter tests."""
 
@@ -36,7 +37,7 @@ class GitFastExporterTests(TestCase):
         self.store = MemoryObjectStore()
         self.stream = BytesIO()
         try:
-            from dulwich.fastexport import GitFastExporter
+            from ..fastexport import GitFastExporter
         except ImportError as exc:
             raise SkipTest("python-fastimport not available") from exc
         self.fastexporter = GitFastExporter(self.stream, self.store)
@@ -84,7 +85,7 @@ class GitImportProcessorTests(TestCase):
         super().setUp()
         self.repo = MemoryRepo()
         try:
-            from dulwich.fastexport import GitImportProcessor
+            from ..fastexport import GitImportProcessor
         except ImportError as exc:
             raise SkipTest("python-fastimport not available") from exc
         self.processor = GitImportProcessor(self.repo)
blob - cca943b4b001d5de7089e31f80dddaa012714b54
blob + 6c1c19d4f8a878ec5d1a75bed008e22e70e6e035
--- dulwich/tests/test_file.py
+++ dulwich/tests/test_file.py
@@ -24,10 +24,11 @@ import shutil
 import sys
 import tempfile
 
-from dulwich.file import FileLocked, GitFile, _fancy_rename
 from dulwich.tests import SkipTest, TestCase
 
+from ..file import FileLocked, GitFile, _fancy_rename
 
+
 class FancyRenameTests(TestCase):
     def setUp(self):
         super().setUp()
blob - 4f30fe5a76873c591f7dc0e9930e28b2e652cbb6
blob + 661ad3101d7c657e84efd6699aacb64f6ec04cd6
--- dulwich/tests/test_grafts.py
+++ dulwich/tests/test_grafts.py
@@ -23,13 +23,13 @@ import os
 import shutil
 import tempfile
 
-from dulwich.errors import ObjectFormatException
-from dulwich.objects import Tree
-from dulwich.repo import (MemoryRepo, Repo, parse_graftpoints,
-                          serialize_graftpoints)
 from dulwich.tests import TestCase
 
+from ..errors import ObjectFormatException
+from ..objects import Tree
+from ..repo import MemoryRepo, Repo, parse_graftpoints, serialize_graftpoints
 
+
 def makesha(digit):
     return (str(digit).encode("ascii") * 40)[:40]
 
blob - d4be7f171be5e91716590b5ba60be62caba4906f
blob + 09a27fb6ac13601e5cd1f929b4451341f2fab11e
--- dulwich/tests/test_graph.py
+++ dulwich/tests/test_graph.py
@@ -20,12 +20,13 @@
 
 """Tests for dulwich.graph."""
 
-from dulwich.graph import _find_lcas, can_fast_forward
-from dulwich.repo import MemoryRepo
 from dulwich.tests import TestCase
-from dulwich.tests.utils import make_commit
 
+from ..graph import _find_lcas, can_fast_forward
+from ..repo import MemoryRepo
+from .utils import make_commit
 
+
 class FindMergeBaseTests(TestCase):
     @staticmethod
     def run_test(dag, inputs):
blob - 79cdc7bc76e4bcc0688878cb84ea83718eb6993c
blob + d18c3d8a9f4d4e5c77529f392098111e25ae53ac
--- dulwich/tests/test_greenthreads.py
+++ dulwich/tests/test_greenthreads.py
@@ -22,10 +22,11 @@
 
 import time
 
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Blob, Commit, Tree, parse_timezone
 from dulwich.tests import TestCase, skipIf
 
+from ..object_store import MemoryObjectStore
+from ..objects import Blob, Commit, Tree, parse_timezone
+
 try:
     import gevent  # noqa: F401
 
@@ -34,7 +35,7 @@ except ImportError:
     gevent_support = False
 
 if gevent_support:
-    from dulwich.greenthreads import GreenThreadsMissingObjectFinder
+    from ..greenthreads import GreenThreadsMissingObjectFinder
 
 skipmsg = "Gevent library is not installed"
 
blob - ebd8098bedfb6bf5d8b7697efb7f2f3b46650ea5
blob + a78b2c868b700a98341ab2287377a6fd3bc0937a
--- dulwich/tests/test_hooks.py
+++ dulwich/tests/test_hooks.py
@@ -26,11 +26,11 @@ import sys
 import tempfile
 
 from dulwich import errors
-from dulwich.hooks import (CommitMsgShellHook, PostCommitShellHook,
-                           PreCommitShellHook)
 from dulwich.tests import TestCase
 
+from ..hooks import CommitMsgShellHook, PostCommitShellHook, PreCommitShellHook
 
+
 class ShellHookTests(TestCase):
     def setUp(self):
         super().setUp()
blob - b7f1d38b8341204ea9c553f56e173b91ea668e57
blob + dbd1f2cedf4b8113375a87f1c23e8c92858a1685
--- dulwich/tests/test_ignore.py
+++ dulwich/tests/test_ignore.py
@@ -26,12 +26,12 @@ import shutil
 import tempfile
 from io import BytesIO
 
-from dulwich.ignore import (IgnoreFilter, IgnoreFilterManager,
-                            IgnoreFilterStack, Pattern, match_pattern,
-                            read_ignore_patterns, translate)
-from dulwich.repo import Repo
 from dulwich.tests import TestCase
 
+from ..ignore import (IgnoreFilter, IgnoreFilterManager, IgnoreFilterStack,
+                      Pattern, match_pattern, read_ignore_patterns, translate)
+from ..repo import Repo
+
 POSITIVE_MATCH_TESTS = [
     (b"foo.c", b"*.c"),
     (b".c", b"*.c"),
blob - 0ff4d8b9053e368c3ab0c27726d6463542d6327a
blob + d94a0108101f8cd924aa68311ffd415849121f03
--- dulwich/tests/test_index.py
+++ dulwich/tests/test_index.py
@@ -30,17 +30,17 @@ import sys
 import tempfile
 from io import BytesIO
 
-from dulwich.index import (Index, IndexEntry, _fs_to_tree_path,
-                           _tree_to_fs_path, build_index_from_tree,
-                           cleanup_mode, commit_tree, get_unstaged_changes,
-                           index_entry_from_stat, read_index, read_index_dict,
-                           validate_path_element_default,
-                           validate_path_element_ntfs, write_cache_time,
-                           write_index, write_index_dict)
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import S_IFGITLINK, Blob, Commit, Tree
-from dulwich.repo import Repo
 from dulwich.tests import TestCase, skipIf
+
+from ..index import (Index, IndexEntry, _fs_to_tree_path, _tree_to_fs_path,
+                     build_index_from_tree, cleanup_mode, commit_tree,
+                     get_unstaged_changes, index_entry_from_stat, read_index,
+                     read_index_dict, validate_path_element_default,
+                     validate_path_element_ntfs, write_cache_time, write_index,
+                     write_index_dict)
+from ..object_store import MemoryObjectStore
+from ..objects import S_IFGITLINK, Blob, Commit, Tree
+from ..repo import Repo
 
 
 def can_symlink():
blob - 6f54d4b3b749573716f33b550fe9620c71699bd7
blob + 49d95d81743e9194de5157577350810c91fbc608
--- dulwich/tests/test_line_ending.py
+++ dulwich/tests/test_line_ending.py
@@ -21,13 +21,14 @@
 
 """Tests for the line ending conversion."""
 
-from dulwich.line_ending import (convert_crlf_to_lf, convert_lf_to_crlf,
-                                 get_checkin_filter_autocrlf,
-                                 get_checkout_filter_autocrlf, normalize_blob)
-from dulwich.objects import Blob
 from dulwich.tests import TestCase
 
+from ..line_ending import (convert_crlf_to_lf, convert_lf_to_crlf,
+                           get_checkin_filter_autocrlf,
+                           get_checkout_filter_autocrlf, normalize_blob)
+from ..objects import Blob
 
+
 class LineEndingConversion(TestCase):
     """Test the line ending conversion functions in various cases"""
 
blob - 08a882a50924fa6180256562055ed5e6aa8a3e0a
blob + bbb392f16fb45ccd75df163c86cc41091eb76b68
--- dulwich/tests/test_mailmap.py
+++ dulwich/tests/test_mailmap.py
@@ -23,7 +23,7 @@
 from io import BytesIO
 from unittest import TestCase
 
-from dulwich.mailmap import Mailmap, read_mailmap
+from ..mailmap import Mailmap, read_mailmap
 
 
 class ReadMailmapTests(TestCase):
blob - ba4eb76a37894f8aa0dd9f9bd43a9a674559814c
blob + 5423b18b06c28033ef9ed89412f68326c25eb863
--- dulwich/tests/test_missing_obj_finder.py
+++ dulwich/tests/test_missing_obj_finder.py
@@ -18,12 +18,13 @@
 # License, Version 2.0.
 #
 
-from dulwich.object_store import MemoryObjectStore, MissingObjectFinder
-from dulwich.objects import Blob
 from dulwich.tests import TestCase
-from dulwich.tests.utils import build_commit_graph, make_object, make_tag
 
+from ..object_store import MemoryObjectStore, MissingObjectFinder
+from ..objects import Blob
+from .utils import build_commit_graph, make_object, make_tag
 
+
 class MissingObjectFinderTest(TestCase):
     def setUp(self):
         super().setUp()
blob - 7ab7fd99a5751f7906443603095cc3feb90ee6e4
blob + b65463ed8dba1c52ec42ee85d384cc80c3cfd82d
--- dulwich/tests/test_object_store.py
+++ dulwich/tests/test_object_store.py
@@ -30,19 +30,20 @@ from contextlib import closing
 from io import BytesIO
 from unittest import skipUnless
 
-from dulwich.errors import NotTreeError
-from dulwich.index import commit_tree
-from dulwich.object_store import (DiskObjectStore, MemoryObjectStore,
-                                  ObjectStoreGraphWalker, OverlayObjectStore,
-                                  commit_tree_changes, iter_tree_contents,
-                                  peel_sha, read_packs_file, tree_lookup_path)
-from dulwich.objects import (S_IFGITLINK, Blob, EmptyFileException,
-                             SubmoduleEncountered, Tree, TreeEntry, sha_to_hex)
-from dulwich.pack import REF_DELTA, write_pack_objects
-from dulwich.protocol import DEPTH_INFINITE
 from dulwich.tests import TestCase
-from dulwich.tests.utils import build_pack, make_object, make_tag
 
+from ..errors import NotTreeError
+from ..index import commit_tree
+from ..object_store import (DiskObjectStore, MemoryObjectStore,
+                            ObjectStoreGraphWalker, OverlayObjectStore,
+                            commit_tree_changes, iter_tree_contents, peel_sha,
+                            read_packs_file, tree_lookup_path)
+from ..objects import (S_IFGITLINK, Blob, EmptyFileException,
+                       SubmoduleEncountered, Tree, TreeEntry, sha_to_hex)
+from ..pack import REF_DELTA, write_pack_objects
+from ..protocol import DEPTH_INFINITE
+from .utils import build_pack, make_object, make_tag
+
 try:
     from unittest.mock import patch
 except ImportError:
blob - 281c2df54c1f0dc37a9aca7bdc280d5f72bf371e
blob + 5b189fb9211eebe29160b5cc95acec3fefd2a73b
--- dulwich/tests/test_objects.py
+++ dulwich/tests/test_objects.py
@@ -30,18 +30,17 @@ from contextlib import contextmanager
 from io import BytesIO
 from itertools import permutations
 
-from dulwich.errors import ObjectFormatException
-from dulwich.objects import (MAX_TIME, Blob, Commit, ShaFile, Tag, Tree,
-                             TreeEntry, _parse_tree_py, _sorted_tree_items_py,
-                             check_hexsha, check_identity, format_timezone,
-                             hex_to_filename, hex_to_sha, object_class,
-                             parse_timezone, parse_tree,
-                             pretty_format_tree_entry, sha_to_hex,
-                             sorted_tree_items)
 from dulwich.tests import TestCase
-from dulwich.tests.utils import (ext_functest_builder, functest_builder,
-                                 make_commit, make_object)
 
+from ..errors import ObjectFormatException
+from ..objects import (MAX_TIME, Blob, Commit, ShaFile, Tag, Tree, TreeEntry,
+                       _parse_tree_py, _sorted_tree_items_py, check_hexsha,
+                       check_identity, format_timezone, hex_to_filename,
+                       hex_to_sha, object_class, parse_timezone, parse_tree,
+                       pretty_format_tree_entry, sha_to_hex, sorted_tree_items)
+from .utils import (ext_functest_builder, functest_builder, make_commit,
+                    make_object)
+
 a_sha = b"6f670c0fb53f9463760b7295fbb814e965fb20c8"
 b_sha = b"2969be3e8ee1c0222396a5611407e4769f14e54b"
 c_sha = b"954a536f7819d40e6f637f849ee187dd10066349"
blob - cf539b33b480694d87a8f9cfa7b687345983bbb7
blob + 586682bb27d73d74475cb11c39b8b3af2b25997c
--- dulwich/tests/test_objectspec.py
+++ dulwich/tests/test_objectspec.py
@@ -23,15 +23,16 @@
 # TODO: Round-trip parse-serialize-parse and serialize-parse-serialize tests.
 
 
-from dulwich.objects import Blob
-from dulwich.objectspec import (parse_commit, parse_commit_range, parse_object,
-                                parse_ref, parse_refs, parse_reftuple,
-                                parse_reftuples, parse_tree)
-from dulwich.repo import MemoryRepo
 from dulwich.tests import TestCase
-from dulwich.tests.utils import build_commit_graph
 
+from ..objects import Blob
+from ..objectspec import (parse_commit, parse_commit_range, parse_object,
+                          parse_ref, parse_refs, parse_reftuple,
+                          parse_reftuples, parse_tree)
+from ..repo import MemoryRepo
+from .utils import build_commit_graph
 
+
 class ParseObjectTests(TestCase):
     """Test parse_object."""
 
blob - e9387bc69128f2a9e0054fe03a1a1934269f0d7f
blob + 2b50dd02bcecfecc6b4a0d02513caefc3a1bedaf
--- dulwich/tests/test_pack.py
+++ dulwich/tests/test_pack.py
@@ -30,20 +30,20 @@ import zlib
 from hashlib import sha1
 from io import BytesIO
 
-from dulwich.errors import ApplyDeltaError, ChecksumMismatch
-from dulwich.file import GitFile
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Blob, Commit, Tree, hex_to_sha, sha_to_hex
-from dulwich.pack import (OFS_DELTA, REF_DELTA, DeltaChainIterator,
-                          MemoryPackIndex, Pack, PackData, PackStreamReader,
-                          UnpackedObject, _delta_encode_size,
-                          _encode_copy_operation, apply_delta,
-                          compute_file_sha, create_delta, deltify_pack_objects,
-                          load_pack_index, read_zlib_chunks, unpack_object,
-                          write_pack, write_pack_header, write_pack_index_v1,
-                          write_pack_index_v2, write_pack_object)
 from dulwich.tests import TestCase
-from dulwich.tests.utils import build_pack, make_object
+
+from ..errors import ApplyDeltaError, ChecksumMismatch
+from ..file import GitFile
+from ..object_store import MemoryObjectStore
+from ..objects import Blob, Commit, Tree, hex_to_sha, sha_to_hex
+from ..pack import (OFS_DELTA, REF_DELTA, DeltaChainIterator, MemoryPackIndex,
+                    Pack, PackData, PackStreamReader, UnpackedObject,
+                    _delta_encode_size, _encode_copy_operation, apply_delta,
+                    compute_file_sha, create_delta, deltify_pack_objects,
+                    load_pack_index, read_zlib_chunks, unpack_object,
+                    write_pack, write_pack_header, write_pack_index_v1,
+                    write_pack_index_v2, write_pack_object)
+from .utils import build_pack, make_object
 
 pack1_sha = b"bc63ddad95e7321ee734ea11a7a62d314e0d7481"
 
blob - c202017fd341c228234bcc6f2a9e0373ccf081db
blob + f9b685a0284e84648c0bcbee8af23133871e38b5
--- dulwich/tests/test_patch.py
+++ dulwich/tests/test_patch.py
@@ -22,13 +22,13 @@
 
 from io import BytesIO, StringIO
 
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import S_IFGITLINK, Blob, Commit, Tree
-from dulwich.patch import (get_summary, git_am_patch_split, write_blob_diff,
-                           write_commit_patch, write_object_diff,
-                           write_tree_diff)
 from dulwich.tests import SkipTest, TestCase
 
+from ..object_store import MemoryObjectStore
+from ..objects import S_IFGITLINK, Blob, Commit, Tree
+from ..patch import (get_summary, git_am_patch_split, write_blob_diff,
+                     write_commit_patch, write_object_diff, write_tree_diff)
+
 
 class WriteCommitPatchTests(TestCase):
     def test_simple_bytesio(self):
blob - ea6f5fb9b8458b87156457f4b484c2fc789daf67
blob + a020b22bd6c6ec680fc3f01cdc72c61f2deacf62
--- dulwich/tests/test_porcelain.py
+++ dulwich/tests/test_porcelain.py
@@ -36,16 +36,17 @@ from io import BytesIO, StringIO
 from unittest import skipIf
 
 from dulwich import porcelain
-from dulwich.diff_tree import tree_changes
-from dulwich.errors import CommitError
-from dulwich.objects import ZERO_SHA, Blob, Tag, Tree
-from dulwich.porcelain import CheckoutError
-from dulwich.repo import NoIndexPresent, Repo
-from dulwich.server import DictBackend
 from dulwich.tests import TestCase
-from dulwich.tests.utils import build_commit_graph, make_commit, make_object
-from dulwich.web import make_server, make_wsgi_chain
 
+from ..diff_tree import tree_changes
+from ..errors import CommitError
+from ..objects import ZERO_SHA, Blob, Tag, Tree
+from ..porcelain import CheckoutError
+from ..repo import NoIndexPresent, Repo
+from ..server import DictBackend
+from ..web import make_server, make_wsgi_chain
+from .utils import build_commit_graph, make_commit, make_object
+
 try:
     import gpg
 except ImportError:
blob - 1ad66ff2449b1a87dc3f5f1f07bab5dabab95352
blob + a586fe67f0da021c5763298491fb94e93954b539
--- dulwich/tests/test_protocol.py
+++ dulwich/tests/test_protocol.py
@@ -23,13 +23,13 @@
 
 from io import BytesIO
 
-from dulwich.errors import HangupException
-from dulwich.protocol import (MULTI_ACK, MULTI_ACK_DETAILED, SINGLE_ACK,
-                              BufferedPktLineWriter, GitProtocolError,
-                              PktLineParser, Protocol, ReceivableProtocol,
-                              ack_type, extract_capabilities,
-                              extract_want_line_capabilities)
 from dulwich.tests import TestCase
+
+from ..errors import HangupException
+from ..protocol import (MULTI_ACK, MULTI_ACK_DETAILED, SINGLE_ACK,
+                        BufferedPktLineWriter, GitProtocolError, PktLineParser,
+                        Protocol, ReceivableProtocol, ack_type,
+                        extract_capabilities, extract_want_line_capabilities)
 
 
 class BaseProtocolTests:
blob - 973354cf0a3c7c74ca9b42afeff55dd342497fda
blob + b15b381b3040401cf374032cf621e42fbb111238
--- dulwich/tests/test_reflog.py
+++ dulwich/tests/test_reflog.py
@@ -22,12 +22,13 @@
 
 from io import BytesIO
 
-from dulwich.objects import ZERO_SHA
-from dulwich.reflog import (drop_reflog_entry, format_reflog_line,
-                            parse_reflog_line, read_reflog)
 from dulwich.tests import TestCase
 
+from ..objects import ZERO_SHA
+from ..reflog import (drop_reflog_entry, format_reflog_line, parse_reflog_line,
+                      read_reflog)
 
+
 class ReflogLineTests(TestCase):
     def test_format(self):
         self.assertEqual(
blob - f318b38135a1e5eab0c3261a017a9dce6cbf2049
blob + 7abff718e356dd5660e8ef9945c0c5967546e905
--- dulwich/tests/test_refs.py
+++ dulwich/tests/test_refs.py
@@ -26,16 +26,16 @@ import tempfile
 from io import BytesIO
 
 from dulwich import errors
-from dulwich.file import GitFile
-from dulwich.objects import ZERO_SHA
-from dulwich.refs import (DictRefsContainer, InfoRefsContainer, SymrefLoop,
-                          _split_ref_line, check_ref_format,
-                          parse_symref_value, read_packed_refs,
-                          read_packed_refs_with_peeled, strip_peeled_refs,
-                          write_packed_refs)
-from dulwich.repo import Repo
 from dulwich.tests import SkipTest, TestCase
-from dulwich.tests.utils import open_repo, tear_down_repo
+
+from ..file import GitFile
+from ..objects import ZERO_SHA
+from ..refs import (DictRefsContainer, InfoRefsContainer, SymrefLoop,
+                    _split_ref_line, check_ref_format, parse_symref_value,
+                    read_packed_refs, read_packed_refs_with_peeled,
+                    strip_peeled_refs, write_packed_refs)
+from ..repo import Repo
+from .utils import open_repo, tear_down_repo
 
 
 class CheckRefFormatTests(TestCase):
blob - bcb827796de11c271ad45a28261de67c0b6c6d27
blob + f48fa7642a02e46b16cf61ede8cdce25ffce0b3f
--- dulwich/tests/test_repository.py
+++ dulwich/tests/test_repository.py
@@ -30,15 +30,15 @@ import tempfile
 import warnings
 
 from dulwich import errors, objects, porcelain
-from dulwich.config import Config
-from dulwich.errors import NotGitRepository
-from dulwich.object_store import tree_lookup_path
-from dulwich.repo import (InvalidUserIdentity, MemoryRepo, Repo,
-                          UnsupportedExtension, UnsupportedVersion,
-                          check_user_identity)
 from dulwich.tests import TestCase, skipIf
-from dulwich.tests.utils import (open_repo, setup_warning_catcher,
-                                 tear_down_repo)
+
+from ..config import Config
+from ..errors import NotGitRepository
+from ..object_store import tree_lookup_path
+from ..repo import (InvalidUserIdentity, MemoryRepo, Repo,
+                    UnsupportedExtension, UnsupportedVersion,
+                    check_user_identity)
+from .utils import open_repo, setup_warning_catcher, tear_down_repo
 
 missing_sha = b"b91fa4d900e17e99b433218e988c4eb4a3e9a097"
 
blob - c5404d0096e1301d679dcf724c5f1854af0e3900
blob + ea76e7666fd25a7318738076b6942974abe55333
--- dulwich/tests/test_server.py
+++ dulwich/tests/test_server.py
@@ -26,21 +26,21 @@ import sys
 import tempfile
 from io import BytesIO
 
-from dulwich.errors import (GitProtocolError, HangupException,
-                            NotGitRepository, UnexpectedCommandError)
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Tree
-from dulwich.protocol import ZERO_SHA, format_capability_line
-from dulwich.repo import MemoryRepo, Repo
-from dulwich.server import (Backend, DictBackend, FileSystemBackend,
-                            MultiAckDetailedGraphWalkerImpl,
-                            MultiAckGraphWalkerImpl, PackHandler,
-                            ReceivePackHandler, SingleAckGraphWalkerImpl,
-                            UploadPackHandler, _find_shallow,
-                            _ProtocolGraphWalker, _split_proto_line,
-                            serve_command, update_server_info)
 from dulwich.tests import TestCase
-from dulwich.tests.utils import make_commit, make_tag
+
+from ..errors import (GitProtocolError, HangupException, NotGitRepository,
+                      UnexpectedCommandError)
+from ..object_store import MemoryObjectStore
+from ..objects import Tree
+from ..protocol import ZERO_SHA, format_capability_line
+from ..repo import MemoryRepo, Repo
+from ..server import (Backend, DictBackend, FileSystemBackend,
+                      MultiAckDetailedGraphWalkerImpl, MultiAckGraphWalkerImpl,
+                      PackHandler, ReceivePackHandler,
+                      SingleAckGraphWalkerImpl, UploadPackHandler,
+                      _find_shallow, _ProtocolGraphWalker, _split_proto_line,
+                      serve_command, update_server_info)
+from .utils import make_commit, make_tag
 
 ONE = b"1" * 40
 TWO = b"2" * 40
blob - c95d335892ac7d9674d60cb6f6dc4a7be5402749
blob + 5760ef5ce567277a61a22776957cb93b3e897e2b
--- dulwich/tests/test_utils.py
+++ dulwich/tests/test_utils.py
@@ -20,12 +20,13 @@
 
 """Tests for git test utilities."""
 
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Blob
 from dulwich.tests import TestCase
-from dulwich.tests.utils import build_commit_graph, make_object
 
+from ..object_store import MemoryObjectStore
+from ..objects import Blob
+from .utils import build_commit_graph, make_object
 
+
 class BuildCommitGraphTest(TestCase):
     def setUp(self):
         super().setUp()
blob - 9e1922fa22ef432a1f698ef14b478bddc515d2bf
blob + 14312d28e9cbb91b2b1ed3a1264bbc4d9e728404
--- dulwich/tests/test_walk.py
+++ dulwich/tests/test_walk.py
@@ -23,16 +23,17 @@
 from itertools import permutations
 from unittest import expectedFailure
 
-from dulwich.diff_tree import (CHANGE_MODIFY, CHANGE_RENAME, RenameDetector,
-                               TreeChange)
-from dulwich.errors import MissingCommitError
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Blob, Commit
 from dulwich.tests import TestCase
-from dulwich.tests.utils import F, build_commit_graph, make_object, make_tag
-from dulwich.walk import ORDER_TOPO, WalkEntry, Walker, _topo_reorder
 
+from ..diff_tree import (CHANGE_MODIFY, CHANGE_RENAME, RenameDetector,
+                         TreeChange)
+from ..errors import MissingCommitError
+from ..object_store import MemoryObjectStore
+from ..objects import Blob, Commit
+from ..walk import ORDER_TOPO, WalkEntry, Walker, _topo_reorder
+from .utils import F, build_commit_graph, make_object, make_tag
 
+
 class TestWalkEntry:
     def __init__(self, commit, changes):
         self.commit = commit
blob - f4ff269b06475b41ae5d4a23182516ab5f16e891
blob + c384b287127674957ac079753688448b3eee2132
--- dulwich/tests/test_web.py
+++ dulwich/tests/test_web.py
@@ -26,19 +26,20 @@ import re
 from io import BytesIO
 from typing import Type
 
-from dulwich.object_store import MemoryObjectStore
-from dulwich.objects import Blob
-from dulwich.repo import BaseRepo, MemoryRepo
-from dulwich.server import DictBackend
 from dulwich.tests import TestCase
-from dulwich.tests.utils import make_object, make_tag
-from dulwich.web import (HTTP_ERROR, HTTP_FORBIDDEN, HTTP_NOT_FOUND, HTTP_OK,
-                         GunzipFilter, HTTPGitApplication, HTTPGitRequest,
-                         _LengthLimitedFile, get_idx_file, get_info_packs,
-                         get_info_refs, get_loose_object, get_pack_file,
-                         get_text_file, handle_service_request, send_file)
 
+from ..object_store import MemoryObjectStore
+from ..objects import Blob
+from ..repo import BaseRepo, MemoryRepo
+from ..server import DictBackend
+from ..web import (HTTP_ERROR, HTTP_FORBIDDEN, HTTP_NOT_FOUND, HTTP_OK,
+                   GunzipFilter, HTTPGitApplication, HTTPGitRequest,
+                   _LengthLimitedFile, get_idx_file, get_info_packs,
+                   get_info_refs, get_loose_object, get_pack_file,
+                   get_text_file, handle_service_request, send_file)
+from .utils import make_object, make_tag
 
+
 class MinimalistWSGIInputStream:
     """WSGI input stream with no 'seek()' and 'tell()' methods."""
 
blob - c7a8897a6b0d27993228280a07bf9b7b5fb44171
blob + 0b19960e57207c4a0e5ee433ebb7dd406ea8b230
--- dulwich/tests/utils.py
+++ dulwich/tests/utils.py
@@ -29,14 +29,15 @@ import time
 import types
 import warnings
 
-from dulwich.index import commit_tree
-from dulwich.objects import Commit, FixedSha, Tag, object_class
-from dulwich.pack import (DELTA_TYPES, OFS_DELTA, REF_DELTA, SHA1Writer,
-                          create_delta, obj_sha, write_pack_header,
-                          write_pack_object)
-from dulwich.repo import Repo
 from dulwich.tests import SkipTest, skipIf  # noqa: F401
 
+from ..index import commit_tree
+from ..objects import Commit, FixedSha, Tag, object_class
+from ..pack import (DELTA_TYPES, OFS_DELTA, REF_DELTA, SHA1Writer,
+                    create_delta, obj_sha, write_pack_header,
+                    write_pack_object)
+from ..repo import Repo
+
 # Plain files are very frequently used in tests, so let the mode be very short.
 F = 0o100644  # Shorthand mode for Files.
 
blob - dbbbb938837b1ecf3b516b6e2cc1e4c910e9bf5a
blob + e57a12aca171db2f7165c35e7b047545e8451e7b
--- dulwich/walk.py
+++ dulwich/walk.py
@@ -26,10 +26,10 @@ import heapq
 from itertools import chain
 from typing import Deque, List, Optional, Set, Tuple
 
-from dulwich.diff_tree import (RENAME_CHANGE_TYPES, RenameDetector,
-                               tree_changes, tree_changes_for_merge)
-from dulwich.errors import MissingCommitError
-from dulwich.objects import Commit, ObjectID, Tag
+from .diff_tree import (RENAME_CHANGE_TYPES, RenameDetector, tree_changes,
+                        tree_changes_for_merge)
+from .errors import MissingCommitError
+from .objects import Commit, ObjectID, Tag
 
 ORDER_DATE = "date"
 ORDER_TOPO = "topo"
blob - 604450728c81d24a70d9575288508e937ad6c104
blob + 2b0312c3ebfc750697fd79d413340dd5f8937137
--- dulwich/web.py
+++ dulwich/web.py
@@ -32,11 +32,12 @@ from wsgiref.simple_server import (ServerHandler, WSGI
                                    WSGIServer, make_server)
 
 from dulwich import log_utils
-from dulwich.protocol import ReceivableProtocol
-from dulwich.repo import BaseRepo, NotGitRepository, Repo
-from dulwich.server import (DEFAULT_HANDLERS, DictBackend, generate_info_refs,
-                            generate_objects_info_packs)
 
+from .protocol import ReceivableProtocol
+from .repo import BaseRepo, NotGitRepository, Repo
+from .server import (DEFAULT_HANDLERS, DictBackend, generate_info_refs,
+                     generate_objects_info_packs)
+
 logger = log_utils.getLogger(__name__)