commit - a5c8b09f2e040ef4ddfc9b7539a30f8125934fda
commit + b7b12f804e747621a3a8fa6d949998b289ca0857
blob - 54939dc83a90ef3b2982fae4ffb4984afafb2ec3
blob + 659665c21e87afa5cbeafbbb74e328b0d8f16608
--- .github/workflows/pythonpackage.yml
+++ .github/workflows/pythonpackage.yml
if: "matrix.os != 'windows-latest' && matrix.python-version != 'pypy3'"
- name: Install mypy
run: |
- pip install -U mypy types-paramiko types-certifi
+ pip install -U mypy types-paramiko types-certifi types-requests
if: "matrix.python-version != 'pypy3'"
- name: Style checks
run: |
blob - b6841613dca06b36f8bdac79df0d508aa1648935
blob + f81a3e36726e35ffaecbc9ed7af1a139a801eb5c
--- MANIFEST.in
+++ MANIFEST.in
graft dulwich/tests/data
include tox.ini
include dulwich.cfg
-include appveyor.yml
include .testr.conf
-include .travis.yml
blob - b676540d23334b7030edf05c1ca6f6d9cc310cb9
blob + e6809e5671c9611848dbedc5b12f75108647fd8a
--- Makefile
+++ Makefile
coverage-html: coverage
$(COVERAGE) html
+
+.PHONY: apidocs
+
+apidocs:
+ pydoctor --docformat=google dulwich --project-url=https://www.dulwich.io/
blob - b63494263735a2f6758a23bbafb6950c98683faa
blob + f89546cd103dce449639447d94e4e8c6650d2b53
--- NEWS
+++ NEWS
+0.20.35 2022-03-20
+
+ * Document the ``path`` attribute for ``Repo``.
+ (Jelmer Vernooij, #854)
+
+0.20.34 2022-03-14
+
+ * Add support for multivars in configuration.
+ (Jelmer Vernooij, #718)
+
+0.20.33 2022-03-05
+
+ * Fix handling of escaped characters in ignore patterns.
+ (Jelmer Vernooij, #930)
+
+ * Add ``dulwich.contrib.requests_vendor``. (epopcon)
+
+ * Ensure git config is available in a linked working tree.
+ (Jesse Cureton, #926)
+
+0.20.32 2022-01-24
+
+ * Properly close result repository during test.
+ (Jelmer Vernooij, #928)
+
0.20.31 2022-01-21
* Add GitClient.clone(). (Jelmer Vernooij, #920)
blob - 10989e70ddc37e59a0b546b680dcdbc375f5e454
blob + 898d25899cc09937c040d2f8c9a1e9fa914bee87
--- PKG-INFO
+++ PKG-INFO
Metadata-Version: 2.1
Name: dulwich
-Version: 0.20.31
+Version: 0.20.35
Summary: Python Git Library
Home-page: https://www.dulwich.io/
Author: Jelmer Vernooij
blob - 16dc77096737a4595f741dff25e65abb0eef4f3e
blob + 96ad71faa79dddd5cce265c59ee2aaa9482567bd
--- debian/changelog
+++ debian/changelog
-dulwich (0.20.31-1.2) UNRELEASED; urgency=medium
+dulwich (0.20.35-1) UNRELEASED; urgency=medium
* Re-export upstream signing key without extra signatures.
+ * New upstream release.
- -- Jelmer Vernooij <jelmer@debian.org> Sun, 20 Mar 2022 12:59:42 -0000
+ -- Jelmer Vernooij <jelmer@debian.org> Sun, 20 Mar 2022 13:01:46 -0000
dulwich (0.20.31-1.1) unstable; urgency=medium
blob - e313fa9d074b29fbbc1daf5fc705e0caf99fc051
blob + 0280087fb5605eb2c6788bcbc757e3d6e6ca0616
--- dulwich/__init__.py
+++ dulwich/__init__.py
"""Python implementation of the Git file formats and protocols."""
-__version__ = (0, 20, 31)
+__version__ = (0, 20, 35)
blob - d0cedf7479da398329c5c53b34651510a932c13e
blob + 235f80b996fbd0254f44349709de633d1769f7a9
--- dulwich/cli.py
+++ dulwich/cli.py
from dulwich.client import 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.patch import write_tree_diff
from dulwich.repo import Repo
def run(self, args):
opts, args = getopt(args, "", [])
- if args == []:
- print("Usage: dulwich diff COMMITID")
- sys.exit(1)
-
r = Repo(".")
- commit_id = args[0]
- commit = r[commit_id]
+ if args == []:
+ commit_id = b'HEAD'
+ else:
+ commit_id = args[0]
+ commit = parse_commit(r, commit_id)
parent_commit = r[commit.parents[0]]
- write_tree_diff(sys.stdout, r.object_store, parent_commit.tree, commit.tree)
+ porcelain.diff_tree(
+ r, parent_commit.tree, commit.tree, outstream=sys.stdout.buffer)
class cmd_dump_pack(Command):
blob - 0dc009171566b286623cc4f8411cfd1331872c21
blob + 5f684ff047585e234af4dda7a315530501a81b6d
--- dulwich/client.py
+++ dulwich/client.py
raise NotImplementedError(self.send_pack)
def clone(self, path, target_path, mkdir: bool = True, bare=False, origin="origin",
- checkout=None, branch=None, depth=None):
+ checkout=None, branch=None, progress=None, depth=None):
"""Clone a repository."""
from .refs import _set_origin_head, _set_default_branch, _set_head
from .repo import Repo
target_config.write_to_path()
ref_message = b"clone: from " + encoded_path
- result = self.fetch(path, target, depth=depth)
+ result = self.fetch(path, target, progress=progress, depth=depth)
_import_remote_refs(
target.refs, origin, result.refs, message=ref_message)
Honour detected proxy configurations.
Args:
- config: dulwich.config.ConfigDict` instance with Git configuration.
- kwargs: Additional arguments for urllib3.ProxyManager
+ config: `dulwich.config.ConfigDict` instance with Git configuration.
+ override_kwargs: Additional arguments for `urllib3.ProxyManager`
Returns:
`pool_manager_cls` (defaults to `urllib3.ProxyManager`) instance for
basic_auth = urllib3.util.make_headers(basic_auth=credentials)
self.pool_manager.headers.update(basic_auth)
+ self.config = config
+
super(Urllib3HttpGitClient, self).__init__(
base_url=base_url, dumb=dumb, **kwargs)
blob - 65f7de9e6ed5c8aacbec0b0c84dff92f24c76224
blob + 7a91806fad30162070ece5f4ab3913cc08eec8dc
--- dulwich/config.py
+++ dulwich/config.py
import os
import sys
+import warnings
from typing import BinaryIO, Tuple, Optional
-from collections import (
- OrderedDict,
-)
-
try:
from collections.abc import (
Iterable,
return key
-class CaseInsensitiveDict(OrderedDict):
+class CaseInsensitiveOrderedMultiDict(MutableMapping):
+
+ def __init__(self):
+ self._real = []
+ self._keyed = {}
+
@classmethod
def make(cls, dict_in=None):
return out
- def __setitem__(self, key, value, **kwargs):
- key = lower_key(key)
+ def __len__(self):
+ return len(self._keyed)
- super(CaseInsensitiveDict, self).__setitem__(key, value, **kwargs)
+ def keys(self):
+ return self._keyed.keys()
- def __getitem__(self, item):
- key = lower_key(item)
+ def items(self):
+ return iter(self._real)
- return super(CaseInsensitiveDict, self).__getitem__(key)
+ def __iter__(self):
+ return self._keyed.__iter__()
+ def values(self):
+ return self._keyed.values()
+
+ def __setitem__(self, key, value):
+ self._real.append((key, value))
+ self._keyed[lower_key(key)] = value
+
+ def __delitem__(self, key):
+ key = lower_key(key)
+ del self._keyed[key]
+ for i, (actual, unused_value) in reversed(list(enumerate(self._real))):
+ if lower_key(actual) == key:
+ del self._real[i]
+
+ def __getitem__(self, item):
+ return self._keyed[lower_key(item)]
+
def get(self, key, default=SENTINAL):
try:
return self[key]
return default
+ def get_all(self, key):
+ key = lower_key(key)
+ for actual, value in self._real:
+ if lower_key(actual) == key:
+ yield value
+
def setdefault(self, key, default=SENTINAL):
try:
return self[key]
Args:
section: Tuple with section name and optional subsection namee
- subsection: Subsection name
+ name: Variable name
Returns:
Contents of the setting
Raises:
KeyError: if the value is not set
"""
raise NotImplementedError(self.get)
+
+ def get_multivar(self, section, name):
+ """Retrieve the contents of a multivar configuration setting.
+
+ Args:
+ section: Tuple with section name and optional subsection namee
+ name: Variable name
+ Returns:
+ Contents of the setting as iterable
+ Raises:
+ KeyError: if the value is not set
+ """
+ raise NotImplementedError(self.get_multivar)
def get_boolean(self, section, name, default=None):
"""Retrieve a configuration setting as boolean.
section: Tuple with section name and optional subsection namee
name: Name of the configuration value, including section
and optional subsection
- value: value of the setting
+ value: value of the setting
"""
raise NotImplementedError(self.set)
+ def items(self, section):
+ """Iterate over the configuration pairs for a specific section.
+
+ Args:
+ section: Tuple with section name and optional subsection namee
+ Returns:
+ Iterator over (name, value) pairs
+ """
+ raise NotImplementedError(self.items)
+
def iteritems(self, section):
"""Iterate over the configuration pairs for a specific section.
Returns:
Iterator over (name, value) pairs
"""
- raise NotImplementedError(self.iteritems)
+ warnings.warn(
+ "Use %s.items instead." % type(self).__name__,
+ DeprecationWarning,
+ stacklevel=3,
+ )
+ return self.items(section)
def itersections(self):
+ warnings.warn(
+ "Use %s.items instead." % type(self).__name__,
+ DeprecationWarning,
+ stacklevel=3,
+ )
+ return self.sections()
+
+ def sections(self):
"""Iterate over the sections.
Returns: Iterator over section tuples
"""
- raise NotImplementedError(self.itersections)
+ raise NotImplementedError(self.sections)
def has_section(self, name):
"""Check if a specified section exists.
Returns:
boolean indicating whether the section exists
"""
- return name in self.itersections()
+ return name in self.sections()
class ConfigDict(Config, MutableMapping):
if encoding is None:
encoding = sys.getdefaultencoding()
self.encoding = encoding
- self._values = CaseInsensitiveDict.make(values)
+ self._values = CaseInsensitiveOrderedMultiDict.make(values)
def __repr__(self):
return "%s(%r)" % (self.__class__.__name__, self._values)
return section, name
+ def get_multivar(self, section, name):
+ section, name = self._check_section_and_name(section, name)
+
+ if len(section) > 1:
+ try:
+ return self._values[section][name]
+ except KeyError:
+ pass
+
+ return self._values[(section[0],)].get_all(name)
+
def get(self, section, name):
section, name = self._check_section_and_name(section, name)
self._values.setdefault(section)[name] = value
- def iteritems(self, section):
+ def items(self, section):
return self._values.get(section).items()
- def itersections(self):
+ def sections(self):
return self._values.keys()
blob - 5159ee4c27a4cdb6a52d676d1e851ef207216548
blob + 83b1638922dbd682089d554cbf247988cdb75c92
--- dulwich/contrib/diffstat.py
+++ dulwich/contrib/diffstat.py
def _parse_patch(lines):
- """An internal routine to parse a git style diff or patch to generate
- diff stats
+ """Parse a git style diff or patch to generate diff stats.
+
Args:
- lines: list of byte strings "lines" from the diff to be parsed
- Returns: A tuple (names, nametypes, counts) of three lists:
- names = list of repo relative file paths
- nametypes - list of booolean values indicating if file
- is binary (True means binary file)
- counts = list of tuples of (added, deleted) counts for that file
+ lines: list of byte string lines from the diff to be parsed
+ Returns: A tuple (names, is_binary, counts) of three lists
"""
names = []
nametypes = []
2. open Sigil.app to the normal nearly blank template epub it generates when opened
3. use Plugins->Manage Plugins menu and make sure the "Use Bundled Python" checkbox is checked
4. use the "Add Plugin" button to navigate to and add testplugin.zip and then hit "Okay" to exit the Manage Plugins Dialog
-""" # noqa: E501 W293
+"""
testoutput = b""" docs/qt512.7_remove_bad_workaround.patch | 15 ++++++++++++
docs/testplugin_v017.zip | Bin
ci_scripts/macgddeploy.py => ci_scripts/gddeploy.py | 0
docs/qt512.6_backport_009abcd_fix.patch | 26 ---------------------
docs/Building_Sigil_On_MacOSX.txt | 2 +-
- 5 files changed, 16 insertions(+), 27 deletions(-)""" # noqa: W291
+ 5 files changed, 16 insertions(+), 27 deletions(-)"""
# return 0 on success otherwise return -1
result = diffstat(selftest.split(b"\n"))
blob - /dev/null
blob + c7f0183a24082ae1b6e78f35444aa1341ce2e187 (mode 644)
--- /dev/null
+++ dulwich/contrib/requests_vendor.py
+# requests_vendor.py -- requests implementation of the AbstractHttpGitClient interface
+# Copyright (C) 2022 Eden Shalit <epopcop@gmail.com>
+#
+# Dulwich is dual-licensed under the Apache License, Version 2.0 and the GNU
+# General Public License as public by the Free Software Foundation; version 2.0
+# or (at your option) any later version. You can redistribute it and/or
+# modify it under the terms of either of these two licenses.
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+# You should have received a copy of the licenses; if not, see
+# <http://www.gnu.org/licenses/> for a copy of the GNU General Public License
+# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
+# License, Version 2.0.
+
+
+"""Requests HTTP client support for Dulwich.
+
+To use this implementation as the HTTP implementation in Dulwich, override
+the dulwich.client.HttpGitClient attribute:
+
+ >>> from dulwich import client as _mod_client
+ >>> from dulwich.contrib.requests_vendor import RequestsHttpGitClient
+ >>> _mod_client.HttpGitClient = RequestsHttpGitClient
+
+This implementation is experimental and does not have any tests.
+"""
+from io import BytesIO
+
+from requests import Session
+
+from dulwich.client import AbstractHttpGitClient, HTTPUnauthorized, HTTPProxyUnauthorized, default_user_agent_string
+from dulwich.errors import NotGitRepository, GitProtocolError
+
+
+class RequestsHttpGitClient(AbstractHttpGitClient):
+ def __init__(
+ self,
+ base_url,
+ dumb=None,
+ config=None,
+ username=None,
+ password=None,
+ **kwargs
+ ):
+ self._username = username
+ self._password = password
+
+ self.session = get_session(config)
+
+ if username is not None:
+ self.session.auth = (username, password)
+
+ super(RequestsHttpGitClient, self).__init__(
+ base_url=base_url, dumb=dumb, **kwargs)
+
+ def _http_request(self, url, headers=None, data=None, allow_compression=False):
+ req_headers = self.session.headers.copy()
+ if headers is not None:
+ req_headers.update(headers)
+
+ if allow_compression:
+ req_headers["Accept-Encoding"] = "gzip"
+ else:
+ req_headers["Accept-Encoding"] = "identity"
+
+ if data:
+ resp = self.session.post(url, headers=req_headers, data=data)
+ else:
+ resp = self.session.get(url, headers=req_headers)
+
+ if resp.status_code == 404:
+ raise NotGitRepository()
+ if resp.status_code == 401:
+ raise HTTPUnauthorized(resp.headers.get("WWW-Authenticate"), url)
+ if resp.status_code == 407:
+ raise HTTPProxyUnauthorized(resp.headers.get("Proxy-Authenticate"), url)
+ if resp.status_code != 200:
+ raise GitProtocolError(
+ "unexpected http resp %d for %s" % (resp.status_code, url)
+ )
+
+ # Add required fields as stated in AbstractHttpGitClient._http_request
+ resp.content_type = resp.headers.get("Content-Type")
+ resp.redirect_location = ""
+ if resp.history:
+ resp.redirect_location = resp.url
+
+ read = BytesIO(resp.content).read
+
+ return resp, read
+
+
+def get_session(config):
+ session = Session()
+ session.headers.update({"Pragma": "no-cache"})
+
+ proxy_server = user_agent = ca_certs = ssl_verify = None
+
+ if config is not None:
+ try:
+ proxy_server = config.get(b"http", b"proxy")
+ if isinstance(proxy_server, bytes):
+ proxy_server = proxy_server.decode()
+ except KeyError:
+ pass
+
+ try:
+ user_agent = config.get(b"http", b"useragent")
+ if isinstance(user_agent, bytes):
+ user_agent = user_agent.decode()
+ except KeyError:
+ pass
+
+ try:
+ ssl_verify = config.get_boolean(b"http", b"sslVerify")
+ except KeyError:
+ ssl_verify = True
+
+ try:
+ ca_certs = config.get(b"http", b"sslCAInfo")
+ if isinstance(ca_certs, bytes):
+ ca_certs = ca_certs.decode()
+ except KeyError:
+ ca_certs = None
+
+ if user_agent is None:
+ user_agent = default_user_agent_string()
+ session.headers.update({"User-agent": user_agent})
+
+ if ca_certs:
+ session.verify = ca_certs
+ elif ssl_verify is False:
+ session.verify = ssl_verify
+
+ if proxy_server:
+ session.proxies.update({
+ "http": proxy_server,
+ "https": proxy_server
+ })
+ return session
blob - 6e53c52d95fbeb7f6b70c4af39343ffdb57ca07a
blob + e6cabff0f5ef2e55310a09609f2d189b30feb5a6
--- dulwich/diff_tree.py
+++ dulwich/diff_tree.py
store: An ObjectStore for looking up objects.
tree1_id: The SHA of the first Tree object to iterate, or None.
tree2_id: The SHA of the second Tree object to iterate, or None.
- param prune_identical: If True, identical subtrees will not be walked.
+ prune_identical: If True, identical subtrees will not be walked.
Returns:
Iterator over Pairs of TreeEntry objects for each pair of entries
in the trees and their subtrees recursively. If an entry exists in one
"""Count the number of common bytes in two block count dicts.
Args:
- block1: The first dict of block hashcode -> total bytes.
- block2: The second dict of block hashcode -> total bytes.
+ blocks1: The first dict of block hashcode -> total bytes.
+ blocks2: The second dict of block hashcode -> total bytes.
Returns:
The number of bytes in common between blocks1 and blocks2. This is
only approximate due to possible hash collisions.
blob - f34e0dd3f9f2e899e304c9ba41016aec243fb594
blob + 5b596b9aaeef89cf1c7c160d47e87b186f50e3c3
--- dulwich/fastexport.py
+++ dulwich/fastexport.py
Tag,
ZERO_SHA,
)
-from fastimport import ( # noqa: E402
+from fastimport import (
commands,
errors as fastimport_errors,
parser,
processor,
)
-import stat # noqa: E402
+import stat
def split_email(text):
blob - 001abe42b13471c889d2eb464026b8492bfcb3fb
blob + e920ab831bf1663734695d8fc9e477c0ee57e676
--- dulwich/hooks.py
+++ dulwich/hooks.py
class CommitMsgShellHook(ShellHook):
"""commit-msg shell hook
-
- Args:
- args[0]: commit message
- Returns:
- new commit message or None
"""
def __init__(self, controldir):
blob - b75560f35c84987f5fe9a4ab835faf773f428756
blob + 55a821f46c14bf7e8392d1d7d4ca85dd77cf3551
--- dulwich/ignore.py
+++ dulwich/ignore.py
res += b"[^/]*"
elif c == b"?":
res += b"[^/]"
+ elif c == b"\\":
+ res += re.escape(segment[i : i + 1])
+ i += 1
elif c == b"[":
j = i
if j < n and segment[j : j + 1] == b"!":
blob - 2c5a1735a5a870714373032bc92e38bb63c090fd
blob + 309d5cf95a999b0257d02ad7c3b4bd4b0848c291
--- dulwich/index.py
+++ dulwich/index.py
"""Build a file or symlink on disk based on a Git object.
Args:
- obj: The git object
+ blob: The git object
mode: File mode
target_path: Path to write to
honor_filemode: An optional flag to honor core.filemode setting in
Args:
fs_path: Full file system path to file
- st: A stat object
+ mode: File mode
Returns: A `Blob` object
"""
assert isinstance(fs_path, bytes)
Args:
paths: Paths to iterate over
root_path: Root path to access from
- store: Optional store to save new blobs in
+ object_store: Optional store to save new blobs in
Returns: Iterator over path, index_entry
"""
for path in paths:
"""
for path, entry in iter_fresh_entries(index, root_path):
index[path] = path
+
+
+class locked_index(object):
+ """Lock the index while making modifications.
+
+ Works as a context manager.
+ """
+ def __init__(self, path):
+ self._path = path
+
+ def __enter__(self):
+ self._file = GitFile(self._path, "wb")
+ self._index = Index(self._path)
+ return self._index
+
+ def __exit__(self, exc_type, exc_value, traceback):
+ if exc_type is not None:
+ self._file.abort()
+ return
+ try:
+ f = SHA1Writer(self._file)
+ write_index_dict(f, self._index._byname)
+ except BaseException:
+ self._file.abort()
+ else:
+ f.close()
blob - 92341c4fa7cab4cab008bd0d6887e07df8f10fc4
blob + 1f931b63f20787ec9a40a6d28cbce860623d2a84
--- dulwich/line_ending.py
+++ dulwich/line_ending.py
# and <http://www.apache.org/licenses/LICENSE-2.0> for a copy of the Apache
# License, Version 2.0.
#
-""" All line-ending related functions, from conversions to config processing
+"""All line-ending related functions, from conversions to config processing
Line-ending normalization is a complex beast. Here is some notes and details
about how it seems to work.
The normalization is a two-fold process that happens at two moments:
- When reading a file from the index and to the working directory. For example
- when doing a `git clone` or `git checkout` call. We call this process the
+ when doing a ``git clone`` or ``git checkout`` call. We call this process the
read filter in this module.
- When writing a file to the index from the working directory. For example
- when doing a `git add` call. We call this process the write filter in this
+ when doing a ``git add`` call. We call this process the write filter in this
module.
Note that when checking status (getting unstaged changes), whether or not
https://git.kernel.org/pub/scm/git/git.git/tree/convert.c#n46
Dulwich have an implementation with a slightly different heuristic, the
-`is_binary` function in `dulwich.patch`.
+`dulwich.patch.is_binary` function.
The binary detection heuristic implementation is close to the one in JGit:
https://github.com/eclipse/jgit/blob/f6873ffe522bbc3536969a3a3546bf9a819b92bf/org.eclipse.jgit/src/org/eclipse/jgit/diff/RawText.java#L300
There is multiple variables that impact the normalization.
-First, a repository can contains a `.gitattributes` file (or more than one...)
+First, a repository can contains a ``.gitattributes`` file (or more than one...)
that can further customize the operation on some file patterns, for example:
- *.txt text
+ \\*.txt text
-Force all `.txt` files to be treated as text files and to have their lines
+Force all ``.txt`` files to be treated as text files and to have their lines
endings normalized.
- *.jpg -text
+ \\*.jpg -text
-Force all `.jpg` files to be treated as binary files and to not have their
+Force all ``.jpg`` files to be treated as binary files and to not have their
lines endings converted.
- *.vcproj text eol=crlf
+ \\*.vcproj text eol=crlf
-Force all `.vcproj` files to be treated as text files and to have their lines
-endings converted into `CRLF` in working directory no matter the native EOL of
+Force all ``.vcproj`` files to be treated as text files and to have their lines
+endings converted into ``CRLF`` in working directory no matter the native EOL of
the platform.
- *.sh text eol=lf
+ \\*.sh text eol=lf
-Force all `.sh` files to be treated as text files and to have their lines
-endings converted into `LF` in working directory no matter the native EOL of
+Force all ``.sh`` files to be treated as text files and to have their lines
+endings converted into ``LF`` in working directory no matter the native EOL of
the platform.
-If the `eol` attribute is not defined, Git uses the `core.eol` configuration
+If the ``eol`` attribute is not defined, Git uses the ``core.eol`` configuration
value described later.
- * text=auto
+ \\* text=auto
Force all files to be scanned by the text file heuristic detection and to have
their line endings normalized in case they are detected as text files.
-Git also have a obsolete attribute named `crlf` that can be translated to the
+Git also have a obsolete attribute named ``crlf`` that can be translated to the
corresponding text attribute value.
Then there are some configuration option (that can be defined at the
- core.autocrlf
- core.eol
-`core.autocrlf` is taken into account for all files that doesn't have a `text`
-attribute defined in `.gitattributes`; it takes three possible values:
+``core.autocrlf`` is taken into account for all files that doesn't have a ``text``
+attribute defined in ``.gitattributes``; it takes three possible values:
- - `true`: This forces all files on the working directory to have CRLF
+ - ``true``: This forces all files on the working directory to have CRLF
line-endings in the working directory and convert line-endings to LF
when writing to the index. When autocrlf is set to true, eol value is
ignored.
- - `input`: Quite similar to the `true` value but only force the write
+ - ``input``: Quite similar to the ``true`` value but only force the write
filter, ie line-ending of new files added to the index will get their
line-endings converted to LF.
- - `false` (default): No normalization is done.
+ - ``false`` (default): No normalization is done.
-`core.eol` is the top-level configuration to define the line-ending to use
+``core.eol`` is the top-level configuration to define the line-ending to use
when applying the read_filer. It takes three possible values:
- - `lf`: When normalization is done, force line-endings to be `LF` in the
+ - ``lf``: When normalization is done, force line-endings to be ``LF`` in the
working directory.
- - `crlf`: When normalization is done, force line-endings to be `CRLF` in
+ - ``crlf``: When normalization is done, force line-endings to be ``CRLF`` in
the working directory.
- - `native` (default): When normalization is done, force line-endings to be
+ - ``native`` (default): When normalization is done, force line-endings to be
the platform's native line ending.
One thing to remember is when line-ending normalization is done on a file, Git
-always normalize line-ending to `LF` when writing to the index.
+always normalize line-ending to ``LF`` when writing to the index.
There are sources that seems to indicate that Git won't do line-ending
normalization when a file contains mixed line-endings. I think this logic
blob - f6b0db483bbba0874007a906e9fd32a305d95bf4
blob + 5918fa5c48bdc68b61a7969eef2a079f6308c54b
--- dulwich/object_store.py
+++ dulwich/object_store.py
"""Add pack data to this object store.
Args:
- num_items: Number of items to add
+ count: Number of items to add
pack_data: Iterator over pack data tuples
"""
if count == 0:
class ObjectStoreGraphWalker(object):
"""Graph walker that finds what commits are missing from an object store.
- :ivar heads: Revisions without descendants in the local repo
- :ivar get_parents: Function to retrieve parents in the local repo
+ Attributes:
+ heads: Revisions without descendants in the local repo
+ get_parents: Function to retrieve parents in the local repo
"""
def __init__(self, local_heads, get_parents, shallow=None):
blob - 74ade5c1eff423b5dc083664681cd0f3cabc9023
blob + 5c1eb3a6880bb91cdb18a512cfde52b02b1e1990
--- dulwich/objects.py
+++ dulwich/objects.py
This will raise an exception if the time is not valid.
Args:
- time_info: author/committer/tagger info
+ time_seconds: time in seconds
"""
# Prevent overflow error
blob - 5dbbaffbeda8e8cccfb1edefcde3273c583e9a9f
blob + 044e65809841079ebc98cb8ebe5ec15e50005259
--- dulwich/objectspec.py
+++ dulwich/objectspec.py
Args:
lh_container: A RefsContainer object
- hh_container: A RefsContainer object
+ rh_container: A RefsContainer object
refspec: A string
Returns: A tuple with left and right ref
Raises:
Args:
lh_container: A RefsContainer object
- hh_container: A RefsContainer object
+ rh_container: A RefsContainer object
refspecs: A list of refspecs or a string
force: Force overwriting for all reftuples
Returns: A list of refs
Args:
repo: A` Repo` object
- commitish: A string referring to a single commit.
+ committish: A string referring to a single commit.
Returns: A Commit object
Raises:
KeyError: When the reference commits can not be found
blob - 74c1a1fa59090fec5a02a427fa823fe1b1fc983c
blob + e7d969eb9b52e7983d2f3a780038242848a3083b
--- dulwich/pack.py
+++ dulwich/pack.py
if sys.platform == "Plan9":
has_mmap = False
-from dulwich.errors import ( # noqa: E402
+from dulwich.errors import (
ApplyDeltaError,
ChecksumMismatch,
)
-from dulwich.file import GitFile # noqa: E402
-from dulwich.lru_cache import ( # noqa: E402
+from dulwich.file import GitFile
+from dulwich.lru_cache import (
LRUSizeCache,
)
-from dulwich.objects import ( # noqa: E402
+from dulwich.objects import (
ShaFile,
hex_to_sha,
sha_to_hex,
"""Load an index file by path.
Args:
- filename: Path to the index file
+ path: Path to the index file
Returns: A PackIndex loaded from the given path
"""
with GitFile(path, "rb") as f:
Args:
filename: Path to the new pack file (without .pack extension)
- objects: Iterable of (object, path) tuples to write.
- Should provide __len__
- window_size: Delta window size
+ objects: (object, path) tuple iterable to write. Should provide __len__
+ delta_window_size: Delta window size
deltify: Whether to deltify pack objects
compression_level: the zlib compression level
Returns: Tuple with checksum of pack file and index file
Args:
f: File to write to
- objects: Iterable of (object, path) tuples to write.
- Should provide __len__
- window_size: Sliding window size for searching for deltas;
- Set to None for default window size.
+ objects: Iterable of (object, path) tuples to write. Should provide
+ __len__
+ delta_window_size: Sliding window size for searching for deltas;
+ Set to None for default window size.
deltify: Whether to deltify objects
compression_level: the zlib compression level to use
Returns: Dict mapping id -> (offset, crc32 checksum), pack checksum
blob - 95309066ea3b3918b21a7bdac2b7a26d1ff0f0dc
blob + 699864caa0e476d41beda09a4b630442422bd036
--- dulwich/porcelain.py
+++ dulwich/porcelain.py
origin=origin,
checkout=checkout,
branch=branch,
+ progress=errstream.write,
depth=depth,
)
def clean(repo=".", target_dir=None):
"""Remove any untracked files from the target directory recursively
- Equivalent to running `git clean -fd` in target_dir.
+ Equivalent to running ``git clean -fd`` in target_dir.
Args:
repo: Repository where the files may be tracked
show_object(r, o, decode, outstream)
-def diff_tree(repo, old_tree, new_tree, outstream=sys.stdout):
+def diff_tree(repo, old_tree, new_tree, outstream=default_bytes_out_stream):
"""Compares the content and mode of blobs found via two tree objects.
Args:
Args:
repo: Path to repository
remote_location: Location of the remote
- refspec: refspecs to fetch
+ refspecs: refspecs to fetch
outstream: A stream file to write to output
errstream: A stream file to write to errors
"""
Args:
repo: Path to repository or repository object
- ignored: Whether to include ignored files in `untracked`
+ ignored: Whether to include ignored files in untracked
Returns: GitStatus tuple,
staged - dict with lists of staged paths (diff index/HEAD)
unstaged - list of unstaged paths (diff index/working-tree)
Args:
repo: Path to the repository
- tree_ish: Tree id to list
+ treeish: Tree id to list
outstream: Output stream (defaults to stdout)
recursive: Whether to recursively list files
name_only: Only print item name
Args:
repo: Path to the repository
- detach: Create a detached head
+ detached: Create a detached head
target: Branch or committish to switch to
new_branch: New branch to create
"""
return sorted(r.open_index())
+def find_unique_abbrev(object_store, object_id):
+ """For now, just return 7 characters."""
+ # TODO(jelmer): Add some logic here to return a number of characters that
+ # scales relative with the size of the repository
+ return object_id.decode("ascii")[:7]
+
+
def describe(repo):
"""Describe the repository version.
Args:
- projdir: git repository root
+ repo: git repository
Returns: a string description of the current git revision
Examples: "gabcdefh", "v0.1" or "v0.1-5-gabcdefh".
# If there are no tags, return the current commit
if len(sorted_tags) == 0:
- return "g{}".format(r[r.head()].id.decode("ascii")[:7])
+ return "g{}".format(find_unique_abbrev(r.object_store, r[r.head()].id))
# We're now 0 commits from the top
commit_count = 0
blob - e82f08d5b3d2cb245370501143754fb2a0e6afca
blob + 317475c5be36785854bcea0689a3ce26b40d8523
--- dulwich/refs.py
+++ dulwich/refs.py
"""
raise NotImplementedError(self.set_if_equals)
- def add_if_new(self, name, ref):
+ def add_if_new(self, name, ref, committer=None, timestamp=None,
+ timezone=None, message=None):
"""Add a new reference only if it does not already exist.
Args:
name: Ref name
ref: Ref value
- message: Message for reflog
"""
raise NotImplementedError(self.add_if_new)
blob - 93bfe021f0127a20a677900d924f342440be9602
blob + 7c3c3a782b9b206c29f6311985c4f63e279b9ca9
--- dulwich/repo.py
+++ dulwich/repo.py
fullname = None
else:
try:
- gecos = pwd.getpwnam(username).pw_gecos
- except KeyError:
+ gecos = pwd.getpwnam(username).pw_gecos # type: ignore
+ except (KeyError, AttributeError):
fullname = None
else:
if gecos:
class BaseRepo(object):
"""Base class for a git repository.
- :ivar object_store: Dictionary-like object for accessing
+ Attributes:
+ object_store: Dictionary-like object for accessing
the objects
- :ivar refs: Dictionary-like object with the refs in this
+ refs: Dictionary-like object with the refs in this
repository
"""
):
"""Create a new commit.
- If not specified, `committer` and `author` default to
+ If not specified, committer and author default to
get_user_identity(..., 'COMMITTER')
and get_user_identity(..., 'AUTHOR') respectively.
the path of the repository.
To create a new repository, use the Repo.init class method.
+
+ Note that a repository object may hold on to resources such
+ as file handles for performance reasons; call .close() to free
+ up those resources.
+
+ Attributes:
+
+ path (str): Path to the working copy (if it exists) or repository control
+ directory (if the repository is bare)
+ bare (bool): Whether this is a bare repository
"""
def __init__(self, root, object_store=None, bare=None):
For a main working tree, it is identical to controldir().
For a linked working tree, it is the control directory of the
- main working tree."""
-
+ main working tree.
+ """
return self._commondir
def _determine_file_mode(self):
origin=b"origin",
checkout=None,
branch=None,
+ progress=None,
depth=None,
):
"""Clone this repository.
cloned from this repository
branch: Optional branch or tag to be used as HEAD in the new repository
instead of this repository's HEAD.
+ progress: Optional progress function
depth: Depth at which to fetch
Returns: Created repository as `Repo`
"""
"""
from dulwich.config import ConfigFile
- path = os.path.join(self._controldir, "config")
+ path = os.path.join(self._commondir, "config")
try:
return ConfigFile.from_path(path)
except FileNotFoundError:
blob - 7e8da3c90f09becf1309a403d9408927507ed519
blob + 1c5b03526d737831f8872f51a0ceb8c74793d356
--- dulwich/server.py
+++ dulwich/server.py
from dulwich.pack import (
write_pack_objects,
)
-from dulwich.protocol import ( # noqa: F401
+from dulwich.protocol import (
BufferedPktLineWriter,
capability_agent,
CAPABILITIES_REF,
blob - 2b1e37d46a2a0e1407a73a7d28ad76ec45a04710
blob + 1fd839da6664491e553d2413929d81faeadb24d2
--- dulwich/tests/__init__.py
+++ dulwich/tests/__init__.py
def tutorial_test_suite():
- import dulwich.client # noqa: F401
- import dulwich.config # noqa: F401
- import dulwich.index # noqa: F401
- import dulwich.reflog # noqa: F401
- import dulwich.repo # noqa: F401
- import dulwich.server # noqa: F401
+ import dulwich.client
+ import dulwich.config
+ import dulwich.index
+ import dulwich.reflog
+ import dulwich.repo
+ import dulwich.server
import dulwich.patch # noqa: F401
tutorial = [
blob - 965f5c54ccb76ec7544ceecc392b5eb29f270341
blob + 97d835311f22e66de92b4f572277fdfab58fdacc
--- dulwich/tests/compat/test_client.py
+++ dulwich/tests/compat/test_client.py
c = self._client()
self.assertEqual(dest.refs[b"refs/heads/abranch"], dummy_commit)
c.send_pack(self._build_path("/dest"), lambda _: sendrefs, gen_pack)
- self.assertFalse(b"refs/heads/abranch" in dest.refs)
+ self.assertNotIn(b"refs/heads/abranch", dest.refs)
def test_send_new_branch_empty_pack(self):
with repo.Repo(os.path.join(self.gitroot, "dest")) as dest:
blob - e7fa282cf654333f5cd0582e532af865acbd80b2
blob + 8d2459d14b4fbb4cb69b8da4625ee33b1f6854e8
--- dulwich/tests/compat/test_repository.py
+++ dulwich/tests/compat/test_repository.py
self.assertEqual(worktrees[0][1], "(bare)")
self.assertTrue(os.path.samefile(worktrees[0][0], self._mainworktree_repo.path))
+ def test_git_worktree_config(self):
+ """Test that git worktree config parsing matches the git CLI's behavior."""
+ # Set some config value in the main repo using the git CLI
+ require_git_version((2, 7, 0))
+ test_name = "Jelmer"
+ test_email = "jelmer@apache.org"
+ run_git_or_fail(["config", "user.name", test_name], cwd=self._repo.path)
+ run_git_or_fail(["config", "user.email", test_email], cwd=self._repo.path)
+ worktree_cfg = self._worktree_repo.get_config()
+ main_cfg = self._repo.get_config()
+
+ # Assert that both the worktree repo and main repo have the same view of the config,
+ # and that the config matches what we set with the git cli
+ self.assertEqual(worktree_cfg, main_cfg)
+ for c in [worktree_cfg, main_cfg]:
+ self.assertEqual(test_name.encode(), c.get((b"user",), b"name"))
+ self.assertEqual(test_email.encode(), c.get((b"user",), b"email"))
+
+ # Read the config values in the worktree with the git cli and assert they match
+ # the dulwich-parsed configs
+ output_name = run_git_or_fail(["config", "user.name"], cwd=self._mainworktree_repo.path).decode().rstrip("\n")
+ output_email = run_git_or_fail(["config", "user.email"], cwd=self._mainworktree_repo.path).decode().rstrip("\n")
+ self.assertEqual(test_name, output_name)
+ self.assertEqual(test_email, output_email)
+
+
class InitNewWorkingDirectoryTestCase(WorkingTreeTestCase):
"""Test compatibility of Repo.init_new_working_directory."""
blob - 7f0f859409e4b65d8bc44f8d8efe4afff56095c2
blob + 5efa414cdaece60573672bc53a01dc9525ed4cb4
--- dulwich/tests/compat/test_server.py
+++ dulwich/tests/compat/test_server.py
def _check_server(self, dul_server):
receive_pack_handler_cls = dul_server.handlers[b"git-receive-pack"]
caps = receive_pack_handler_cls.capabilities()
- self.assertFalse(b"side-band-64k" in caps)
+ self.assertNotIn(b"side-band-64k", caps)
def _start_server(self, repo):
backend = DictBackend({b"/": repo})
def _check_server(self, server):
receive_pack_handler_cls = server.handlers[b"git-receive-pack"]
caps = receive_pack_handler_cls.capabilities()
- self.assertTrue(b"side-band-64k" in caps)
+ self.assertIn(b"side-band-64k", caps)
blob - 1717b942ad30f42fe2a9338a4e5a37c8979ffe42
blob + 55acf585a0255c3b05b8be4231d4125db3889cdb
--- dulwich/tests/test_client.py
+++ dulwich/tests/test_client.py
class TestGetTransportAndPath(TestCase):
def test_tcp(self):
c, path = get_transport_and_path("git://foo.com/bar/baz")
- self.assertTrue(isinstance(c, TCPGitClient))
+ self.assertIsInstance(c, TCPGitClient)
self.assertEqual("foo.com", c._host)
self.assertEqual(TCP_GIT_PORT, c._port)
self.assertEqual("/bar/baz", path)
def test_tcp_port(self):
c, path = get_transport_and_path("git://foo.com:1234/bar/baz")
- self.assertTrue(isinstance(c, TCPGitClient))
+ self.assertIsInstance(c, TCPGitClient)
self.assertEqual("foo.com", c._host)
self.assertEqual(1234, c._port)
self.assertEqual("/bar/baz", path)
def test_git_ssh_explicit(self):
c, path = get_transport_and_path("git+ssh://foo.com/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_explicit(self):
c, path = get_transport_and_path("ssh://foo.com/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_port_explicit(self):
c, path = get_transport_and_path("git+ssh://foo.com:1234/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(1234, c.port)
self.assertEqual("/bar/baz", path)
def test_username_and_port_explicit_unknown_scheme(self):
c, path = get_transport_and_path("unknown://git@server:7999/dply/stuff.git")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("unknown", c.host)
self.assertEqual("//git@server:7999/dply/stuff.git", path)
def test_username_and_port_explicit(self):
c, path = get_transport_and_path("ssh://git@server:7999/dply/stuff.git")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("git", c.username)
self.assertEqual("server", c.host)
self.assertEqual(7999, c.port)
def test_ssh_abspath_doubleslash(self):
c, path = get_transport_and_path("git+ssh://foo.com//bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_port(self):
c, path = get_transport_and_path("git+ssh://foo.com:1234/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(1234, c.port)
self.assertEqual("/bar/baz", path)
def test_ssh_implicit(self):
c, path = get_transport_and_path("foo:/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_host(self):
c, path = get_transport_and_path("foo.com:/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_user_host(self):
c, path = get_transport_and_path("user@foo.com:/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual("user", c.username)
def test_ssh_relpath(self):
c, path = get_transport_and_path("foo:bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_host_relpath(self):
c, path = get_transport_and_path("foo.com:bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_user_host_relpath(self):
c, path = get_transport_and_path("user@foo.com:bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual("user", c.username)
def test_local(self):
c, path = get_transport_and_path("foo.bar/baz")
- self.assertTrue(isinstance(c, LocalGitClient))
+ self.assertIsInstance(c, LocalGitClient)
self.assertEqual("foo.bar/baz", path)
@skipIf(sys.platform != "win32", "Behaviour only happens on windows.")
def test_local_abs_windows_path(self):
c, path = get_transport_and_path("C:\\foo.bar\\baz")
- self.assertTrue(isinstance(c, LocalGitClient))
+ self.assertIsInstance(c, LocalGitClient)
self.assertEqual("C:\\foo.bar\\baz", path)
def test_error(self):
# Need to use a known urlparse.uses_netloc URL scheme to get the
# expected parsing of the URL on Python versions less than 2.6.5
c, path = get_transport_and_path("prospero://bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
def test_http(self):
url = "https://github.com/jelmer/dulwich"
c, path = get_transport_and_path(url)
- self.assertTrue(isinstance(c, HttpGitClient))
+ self.assertIsInstance(c, HttpGitClient)
self.assertEqual("/jelmer/dulwich", path)
def test_http_auth(self):
c, path = get_transport_and_path(url)
- self.assertTrue(isinstance(c, HttpGitClient))
+ self.assertIsInstance(c, HttpGitClient)
self.assertEqual("/jelmer/dulwich", path)
self.assertEqual("user", c._username)
self.assertEqual("passwd", c._password)
c, path = get_transport_and_path(url, username="user2", password="blah")
- self.assertTrue(isinstance(c, HttpGitClient))
+ self.assertIsInstance(c, HttpGitClient)
self.assertEqual("/jelmer/dulwich", path)
self.assertEqual("user2", c._username)
self.assertEqual("blah", c._password)
c, path = get_transport_and_path(url, username="user2", password="blah")
- self.assertTrue(isinstance(c, HttpGitClient))
+ self.assertIsInstance(c, HttpGitClient)
self.assertEqual("/jelmer/dulwich", path)
self.assertEqual("user", c._username)
self.assertEqual("passwd", c._password)
c, path = get_transport_and_path(url)
- self.assertTrue(isinstance(c, HttpGitClient))
+ self.assertIsInstance(c, HttpGitClient)
self.assertEqual("/jelmer/dulwich", path)
self.assertIs(None, c._username)
self.assertIs(None, c._password)
class TestGetTransportAndPathFromUrl(TestCase):
def test_tcp(self):
c, path = get_transport_and_path_from_url("git://foo.com/bar/baz")
- self.assertTrue(isinstance(c, TCPGitClient))
+ self.assertIsInstance(c, TCPGitClient)
self.assertEqual("foo.com", c._host)
self.assertEqual(TCP_GIT_PORT, c._port)
self.assertEqual("/bar/baz", path)
def test_tcp_port(self):
c, path = get_transport_and_path_from_url("git://foo.com:1234/bar/baz")
- self.assertTrue(isinstance(c, TCPGitClient))
+ self.assertIsInstance(c, TCPGitClient)
self.assertEqual("foo.com", c._host)
self.assertEqual(1234, c._port)
self.assertEqual("/bar/baz", path)
def test_ssh_explicit(self):
c, path = get_transport_and_path_from_url("git+ssh://foo.com/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_port_explicit(self):
c, path = get_transport_and_path_from_url("git+ssh://foo.com:1234/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(1234, c.port)
self.assertEqual("/bar/baz", path)
def test_ssh_homepath(self):
c, path = get_transport_and_path_from_url("git+ssh://foo.com/~/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(None, c.port)
self.assertEqual(None, c.username)
def test_ssh_port_homepath(self):
c, path = get_transport_and_path_from_url("git+ssh://foo.com:1234/~/bar/baz")
- self.assertTrue(isinstance(c, SSHGitClient))
+ self.assertIsInstance(c, SSHGitClient)
self.assertEqual("foo.com", c.host)
self.assertEqual(1234, c.port)
self.assertEqual("/~/bar/baz", path)
def test_http(self):
url = "https://github.com/jelmer/dulwich"
c, path = get_transport_and_path_from_url(url)
- self.assertTrue(isinstance(c, HttpGitClient))
+ self.assertIsInstance(c, HttpGitClient)
self.assertEqual("https://github.com", c.get_url(b"/"))
self.assertEqual("/jelmer/dulwich", path)
url = "https://github.com:9090/jelmer/dulwich"
c, path = get_transport_and_path_from_url(url)
self.assertEqual("https://github.com:9090", c.get_url(b"/"))
- self.assertTrue(isinstance(c, HttpGitClient))
+ self.assertIsInstance(c, HttpGitClient)
self.assertEqual("/jelmer/dulwich", path)
def test_file(self):
c, path = get_transport_and_path_from_url("file:///home/jelmer/foo")
- self.assertTrue(isinstance(c, LocalGitClient))
+ self.assertIsInstance(c, LocalGitClient)
self.assertEqual("/home/jelmer/foo", path)
target = tempfile.mkdtemp()
self.addCleanup(shutil.rmtree, target)
result_repo = c.clone(s.path, target, mkdir=False)
+ self.addCleanup(result_repo.close)
expected = dict(s.get_refs())
expected[b'refs/remotes/origin/HEAD'] = expected[b'HEAD']
expected[b'refs/remotes/origin/master'] = expected[b'refs/heads/master']
blob - 487c2aa87a71268507d4f499917e408a8868ef4e
blob + 39f58c87262e96c0e28783e3f312a4fb7c29a5b9
--- dulwich/tests/test_config.py
+++ dulwich/tests/test_config.py
self.assertEqual(b"bar", cf.get((b"core",), b"foo"))
self.assertEqual(b"bar", cf.get((b"core", b"foo"), b"foo"))
+ def test_from_file_multiple(self):
+ cf = self.from_file(b"[core]\nfoo = bar\nfoo = blah\n")
+ self.assertEqual([b"bar", b"blah"], list(cf.get_multivar((b"core",), b"foo")))
+ self.assertEqual([], list(cf.get_multivar((b"core", ), b"blah")))
+
def test_from_file_utf8_bom(self):
text = "[core]\nfoo = b\u00e4r\n".encode("utf-8-sig")
cf = self.from_file(text)
cf = self.from_file(b"[branch.foo]\nfoo = bar\n")
self.assertEqual(b"bar", cf.get((b"branch", b"foo"), b"foo"))
+ def test_write_preserve_multivar(self):
+ cf = self.from_file(b"[core]\nfoo = bar\nfoo = blah\n")
+ f = BytesIO()
+ cf.write_to_file(f)
+ self.assertEqual(b"[core]\n\tfoo = bar\n\tfoo = blah\n", f.getvalue())
+
def test_write_to_file_empty(self):
c = ConfigFile()
f = BytesIO()
cd[b"a"] = b"b"
self.assertEqual(cd[b"a"], b"b")
- def test_iteritems(self):
+ def test_items(self):
cd = ConfigDict()
cd.set((b"core",), b"foo", b"bla")
cd.set((b"core2",), b"foo", b"bloe")
- self.assertEqual([(b"foo", b"bla")], list(cd.iteritems((b"core",))))
+ self.assertEqual([(b"foo", b"bla")], list(cd.items((b"core",))))
- def test_iteritems_nonexistant(self):
+ def test_items_nonexistant(self):
cd = ConfigDict()
cd.set((b"core2",), b"foo", b"bloe")
- self.assertEqual([], list(cd.iteritems((b"core",))))
+ self.assertEqual([], list(cd.items((b"core",))))
- def test_itersections(self):
+ def test_sections(self):
cd = ConfigDict()
cd.set((b"core2",), b"foo", b"bloe")
- self.assertEqual([(b"core2",)], list(cd.itersections()))
+ self.assertEqual([(b"core2",)], list(cd.sections()))
class StackedConfigTests(TestCase):
blob - 09d55c26914e851357eed4b366f004897a3d15ec
blob + cd2196e30bfe4a74ff5d71bb881b90e838d863b4
--- dulwich/tests/test_fastexport.py
+++ dulwich/tests/test_fastexport.py
)
)
self.assertEqual(2, len(markers))
- self.assertTrue(isinstance(self.repo[markers[b"1"]], Blob))
- self.assertTrue(isinstance(self.repo[markers[b"2"]], Commit))
+ self.assertIsInstance(self.repo[markers[b"1"]], Blob)
+ self.assertIsInstance(self.repo[markers[b"2"]], Commit)
def test_file_add(self):
from fastimport import commands
blob - ec0f4d73817458e7e9e697ec4a90f2e36ba4b06f
blob + cc6d68a5788bad477de2ea137f64e5234083ddfb
--- dulwich/tests/test_file.py
+++ dulwich/tests/test_file.py
def test_readonly(self):
f = GitFile(self.path("foo"), "rb")
- self.assertTrue(isinstance(f, io.IOBase))
+ self.assertIsInstance(f, io.IOBase)
self.assertEqual(b"foo contents", f.read())
self.assertEqual(b"", f.read())
f.seek(4)
blob - 6cb5c6611243da3c836351588f13e1cec027657a
blob + b3a6ab135e31ae9c4413e62cb04f0b72db074786
--- dulwich/tests/test_ignore.py
+++ dulwich/tests/test_ignore.py
(b"**/bla.c", b"(?ms)(.*/)?bla\\.c/?\\Z"),
(b"foo/**/bar", b"(?ms)foo(/.*)?\\/bar/?\\Z"),
(b"foo/bar/*", b"(?ms)foo\\/bar\\/[^/]+/?\\Z"),
+ (b"/foo\\[bar\\]", b"(?ms)foo\\[bar\\]/?\\Z"),
+ (b"/foo[bar]", b"(?ms)foo[bar]/?\\Z"),
+ (b"/foo[0-9]", b"(?ms)foo[0-9]/?\\Z"),
]
with trailing whitespace
with escaped trailing whitespace\\
"""
- ) # noqa: W291
+ )
self.assertEqual(
list(read_ignore_patterns(f)),
[
self.assertFalse(filter.is_ignored(b"foo/bar/"))
self.assertFalse(filter.is_ignored(b"foo/bar/bloe"))
+ def test_regex_special(self):
+ # See https://github.com/dulwich/dulwich/issues/930#issuecomment-1026166429
+ filter = IgnoreFilter([b"/foo\\[bar\\]", b"/foo"])
+ self.assertTrue(filter.is_ignored("foo"))
+ self.assertTrue(filter.is_ignored("foo[bar]"))
+
class IgnoreFilterStackTests(TestCase):
def test_stack_first(self):
filter1 = IgnoreFilter([b"[a].c", b"[b].c", b"![d].c"])
with open(os.path.join(repo.path, 'foo', 'bar'), 'wb') as f:
f.write(b'IGNORED')
-
+
m = IgnoreFilterManager.from_repo(repo)
self.assertTrue(m.is_ignored('foo/bar'))
blob - 7696e3eec71c6c00d994a75f59e2a337d54822e8
blob + 74fb848291178e8cd036b00e96506fdf46c6daf6
--- dulwich/tests/test_lru_cache.py
+++ dulwich/tests/test_lru_cache.py
def test_missing(self):
cache = lru_cache.LRUCache(max_cache=10)
- self.assertFalse("foo" in cache)
+ self.assertNotIn("foo", cache)
self.assertRaises(KeyError, cache.__getitem__, "foo")
cache["foo"] = "bar"
self.assertEqual("bar", cache["foo"])
- self.assertTrue("foo" in cache)
- self.assertFalse("bar" in cache)
+ self.assertIn("foo", cache)
+ self.assertNotIn("bar", cache)
def test_map_None(self):
# Make sure that we can properly map None as a key.
cache = lru_cache.LRUCache(max_cache=10)
- self.assertFalse(None in cache)
+ self.assertNotIn(None, cache)
cache[None] = 1
self.assertEqual(1, cache[None])
cache[None] = 2
# With a max cache of 1, adding 'baz' should pop out 'foo'
cache["baz"] = "biz"
- self.assertFalse("foo" in cache)
- self.assertTrue("baz" in cache)
+ self.assertNotIn("foo", cache)
+ self.assertIn("baz", cache)
self.assertEqual("biz", cache["baz"])
# This must kick out 'foo' because it was the last accessed
cache["nub"] = "in"
- self.assertFalse("foo" in cache)
+ self.assertNotIn("foo", cache)
def test_cleanup(self):
"""Test that we can use a cleanup function."""
self.assertEqual(20, cache.get(2))
self.assertEqual(None, cache.get(3))
obj = object()
- self.assertTrue(obj is cache.get(3, obj))
+ self.assertIs(obj, cache.get(3, obj))
self.assertEqual([2, 1], [n.key for n in cache._walk_lru()])
self.assertEqual(10, cache.get(1))
self.assertEqual([1, 2], [n.key for n in cache._walk_lru()])
blob - 742ce9acc0aae01695b445c9c9108da5ec61e25d
blob + 817f4d15a1a24e84f6b267875d821213814bbe29
--- dulwich/tests/test_missing_obj_finder.py
+++ dulwich/tests/test_missing_obj_finder.py
def assertMissingMatch(self, haves, wants, expected):
for sha, path in self.store.find_missing_objects(haves, wants, set()):
- self.assertTrue(
- sha in expected,
- "(%s,%s) erroneously reported as missing" % (sha, path),
+ self.assertIn(
+ sha,
+ expected,
+ "(%s,%s) erroneously reported as missing" % (sha, path)
)
expected.remove(sha)
blob - 2f0329f2840b84326570efa1fb06f8d84a87407e
blob + 08850a68060621ab80be4cb2e9557d57d431df69
--- dulwich/tests/test_object_store.py
+++ dulwich/tests/test_object_store.py
self.assertRaises(KeyError, lambda: self.store[b"a" * 40])
def test_contains_nonexistant(self):
- self.assertFalse((b"a" * 40) in self.store)
+ self.assertNotIn(b"a" * 40, self.store)
def test_add_objects_empty(self):
self.store.add_objects([])
def test_add_object(self):
self.store.add_object(testobject)
self.assertEqual(set([testobject.id]), set(self.store))
- self.assertTrue(testobject.id in self.store)
+ self.assertIn(testobject.id, self.store)
r = self.store[testobject.id]
self.assertEqual(r, testobject)
data = [(testobject, "mypath")]
self.store.add_objects(data)
self.assertEqual(set([testobject.id]), set(self.store))
- self.assertTrue(testobject.id in self.store)
+ self.assertIn(testobject.id, self.store)
r = self.store[testobject.id]
self.assertEqual(r, testobject)
def test_lookup_blob(self):
o_id = tree_lookup_path(self.get_object, self.tree_id, b"a")[1]
- self.assertTrue(isinstance(self.store[o_id], Blob))
+ self.assertIsInstance(self.store[o_id], Blob)
def test_lookup_tree(self):
o_id = tree_lookup_path(self.get_object, self.tree_id, b"ad")[1]
- self.assertTrue(isinstance(self.store[o_id], Tree))
+ self.assertIsInstance(self.store[o_id], Tree)
o_id = tree_lookup_path(self.get_object, self.tree_id, b"ad/bd")[1]
- self.assertTrue(isinstance(self.store[o_id], Tree))
+ self.assertIsInstance(self.store[o_id], Tree)
o_id = tree_lookup_path(self.get_object, self.tree_id, b"ad/bd/")[1]
- self.assertTrue(isinstance(self.store[o_id], Tree))
+ self.assertIsInstance(self.store[o_id], Tree)
def test_lookup_submodule(self):
tree_lookup_path(self.get_object, self.tree_id, b"d")[1]
blob - d2c37455b8486f7a7a3d3f5f2c1ce8449e2e83e5
blob + 7c8256d34bc4d081583f9b5e430ec7a0c110513f
--- dulwich/tests/test_objects.py
+++ dulwich/tests/test_objects.py
def test_stub_sha(self):
sha = b"5" * 40
c = make_commit(id=sha, message=b"foo")
- self.assertTrue(isinstance(c, Commit))
+ self.assertIsInstance(c, Commit)
self.assertEqual(sha, c.id)
self.assertNotEqual(sha, c.sha())
def test_encoding(self):
c = self.make_commit(encoding=b"iso8859-1")
- self.assertTrue(b"encoding iso8859-1\n" in c.as_raw_string())
+ self.assertIn(b"encoding iso8859-1\n", c.as_raw_string())
def test_short_timestamp(self):
c = self.make_commit(commit_time=30)
def test_timezone(self):
c = self.make_commit(commit_timezone=(5 * 60))
- self.assertTrue(b" +0005\n" in c.as_raw_string())
+ self.assertIn(b" +0005\n", c.as_raw_string())
def test_neg_timezone(self):
c = self.make_commit(commit_timezone=(-1 * 3600))
- self.assertTrue(b" -0100\n" in c.as_raw_string())
+ self.assertIn(b" -0100\n", c.as_raw_string())
def test_deserialize(self):
c = self.make_commit()
Merge ../b
""",
commit.as_raw_string(),
- ) # noqa: W291,W293
+ )
def test_serialize_mergetag(self):
tag = make_object(
Merge ../b
""",
commit.as_raw_string(),
- ) # noqa: W291,W293
+ )
def test_serialize_mergetags(self):
tag = make_object(
Merge ../b
""",
commit.as_raw_string(),
- ) # noqa: W291,W293
+ )
def test_deserialize_mergetag(self):
tag = make_object(
foo
"""
- ) # noqa: W291,W293
+ )
self.assertEqual(b"foo\n", c.message)
self.assertEqual([], c.extra)
self.assertEqual(
3.3.0 version bump and docs
"""
- ) # noqa: W291,W293
+ )
self.assertEqual([], c.extra)
self.assertEqual(
b"""\
actual = do_sort(_TREE_ITEMS)
self.assertEqual(_SORTED_TREE_ITEMS, actual)
- self.assertTrue(isinstance(actual[0], TreeEntry))
+ self.assertIsInstance(actual[0], TreeEntry)
# C/Python implementations may differ in specific error types, but
# should all error on invalid inputs.
oclass = object_class(orig.type_num)
copy = orig.copy()
- self.assertTrue(isinstance(copy, oclass))
+ self.assertIsInstance(copy, oclass)
self.assertEqual(copy, orig)
- self.assertTrue(copy is not orig)
+ self.assertIsNot(copy, orig)
def test_commit_copy(self):
attrs = {
blob - 407893e9725ea126bc6c10657861381eb47b1c52
blob + d8708c906ad2ff1a57620d5fdf265b91bc023077
--- dulwich/tests/test_pack.py
+++ dulwich/tests/test_pack.py
def test_contains(self):
with self.get_pack(pack1_sha) as p:
- self.assertTrue(tree_sha in p)
+ self.assertIn(tree_sha, p)
def test_get(self):
with self.get_pack(pack1_sha) as p:
objs = {o.id: o for o in p.iterobjects()}
self.assertEqual(3, len(objs))
self.assertEqual(sorted(objs), sorted(p.index))
- self.assertTrue(isinstance(objs[a_sha], Blob))
- self.assertTrue(isinstance(objs[tree_sha], Tree))
- self.assertTrue(isinstance(objs[commit_sha], Commit))
+ self.assertIsInstance(objs[a_sha], Blob)
+ self.assertIsInstance(objs[tree_sha], Tree)
+ self.assertIsInstance(objs[commit_sha], Commit)
class TestThinPack(PackTests):
if self._has_crc32_checksum:
self.assertEqual(my_crc, actual_crc)
else:
- self.assertTrue(actual_crc is None)
+ self.assertIsNone(actual_crc)
def test_single(self):
entry_sha = hex_to_sha("6f670c0fb53f9463760b7295fbb814e965fb20c8")
if self._has_crc32_checksum:
self.assertEqual(my_crc, actual_crc)
else:
- self.assertTrue(actual_crc is None)
+ self.assertIsNone(actual_crc)
class BaseTestFilePackIndexWriting(BaseTestPackIndexWriting):
def get_raw_no_repeat(self, bin_sha):
"""Wrapper around store.get_raw that doesn't allow repeat lookups."""
hex_sha = sha_to_hex(bin_sha)
- self.assertFalse(
- hex_sha in self.fetched,
- "Attempted to re-fetch object %s" % hex_sha,
+ self.assertNotIn(
+ hex_sha,
+ self.fetched,
+ "Attempted to re-fetch object %s" % hex_sha
)
self.fetched.add(hex_sha)
return self.store.get_raw(hex_sha)
blob - a553a34a6b6ce0271aa6edb2b7e3aff313a2db72
blob + 38aac88f64c2b9be1578d7f151269b1520b00bf1
--- dulwich/tests/test_patch.py
+++ dulwich/tests/test_patch.py
--
1.7.0.4
-""" # noqa: W291
+"""
c, diff, version = git_am_patch_split(StringIO(text.decode("utf-8")), "utf-8")
self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.committer)
self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.author)
--
1.7.0.4
-""" # noqa: W291
+"""
c, diff, version = git_am_patch_split(BytesIO(text))
self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.committer)
self.assertEqual(b"Jelmer Vernooij <jelmer@samba.org>", c.author)
--
1.7.0.4
-""" # noqa: W291
+"""
c, diff, version = git_am_patch_split(BytesIO(text), "utf-8")
self.assertEqual(
b"""\
--
1.7.0.4
-""" # noqa: W291
+"""
c, diff, version = git_am_patch_split(BytesIO(text), "utf-8")
self.assertEqual(b"Jelmer Vernooij <jelmer@debian.org>", c.author)
self.assertEqual(
class DiffTests(TestCase):
-""" # noqa: W291,W293
+"""
text = (
"""\
From dulwich-users-bounces+jelmer=samba.org@lists.launchpad.net \
"""
% expected_diff
- ) # noqa: W291
+ )
c, diff, version = git_am_patch_split(BytesIO(text))
self.assertEqual(expected_diff, diff)
self.assertEqual(None, version)
blob - 5618066e8105401fe014c7b5e104a5d1e64f9d30
blob + a1d37c0f96ce73b10dd47fda9e180499afedb4ee
--- dulwich/tests/test_porcelain.py
+++ dulwich/tests/test_porcelain.py
author=b"Joe <joe@example.com>",
committer=b"Bob <bob@example.com>",
)
- self.assertTrue(isinstance(sha, bytes))
+ self.assertIsInstance(sha, bytes)
self.assertEqual(len(sha), 40)
def test_unicode(self):
author="Joe <joe@example.com>",
committer="Bob <bob@example.com>",
)
- self.assertTrue(isinstance(sha, bytes))
+ self.assertIsInstance(sha, bytes)
self.assertEqual(len(sha), 40)
def test_no_verify(self):
committer="Bob <bob@example.com>",
no_verify=True,
)
- self.assertTrue(isinstance(sha, bytes))
+ self.assertIsInstance(sha, bytes)
self.assertEqual(len(sha), 40)
target_repo = Repo(target_path)
self.assertEqual(0, len(target_repo.open_index()))
self.assertEqual(c3.id, target_repo.refs[b"refs/tags/foo"])
- self.assertTrue(b"f1" not in os.listdir(target_path))
- self.assertTrue(b"f2" not in os.listdir(target_path))
+ self.assertNotIn(b"f1", os.listdir(target_path))
+ self.assertNotIn(b"f2", os.listdir(target_path))
c = r.get_config()
encoded_path = self.repo.path
if not isinstance(encoded_path, bytes):
self.assertEqual(r.path, target_path)
with Repo(target_path) as r:
self.assertEqual(r.head(), c3.id)
- self.assertTrue("f1" in os.listdir(target_path))
- self.assertTrue("f2" in os.listdir(target_path))
+ self.assertIn("f1", os.listdir(target_path))
+ self.assertIn("f2", os.listdir(target_path))
def test_bare_local_with_checkout(self):
f1_1 = make_object(Blob, data=b"f1")
with Repo(target_path) as r:
r.head()
self.assertRaises(NoIndexPresent, r.open_index)
- self.assertFalse(b"f1" in os.listdir(target_path))
- self.assertFalse(b"f2" in os.listdir(target_path))
+ self.assertNotIn(b"f1", os.listdir(target_path))
+ self.assertNotIn(b"f2", os.listdir(target_path))
def test_no_checkout_with_bare(self):
f1_1 = make_object(Blob, data=b"f1")
author=b"Joe <joe@example.com>",
committer=b"Jane <jane@example.com>",
)
- self.assertTrue(isinstance(sha, bytes))
+ self.assertIsInstance(sha, bytes)
self.assertEqual(len(sha), 40)
tags = self.repo.refs.as_dict(b"refs/tags")
self.assertEqual(list(tags.keys()), [b"tryme"])
tag = self.repo[b"refs/tags/tryme"]
- self.assertTrue(isinstance(tag, Tag))
+ self.assertIsInstance(tag, Tag)
self.assertEqual(b"foo <foo@bar.com>", tag.tagger)
self.assertEqual(b"bar\n", tag.message)
self.assertLess(time.time() - tag.tag_time, 5)
tags = self.repo.refs.as_dict(b"refs/tags")
self.assertEqual(list(tags.keys()), [b"tryme"])
tag = self.repo[b"refs/tags/tryme"]
- self.assertTrue(isinstance(tag, Tag))
+ self.assertIsInstance(tag, Tag)
self.assertEqual(b"foo <foo@bar.com>", tag.tagger)
self.assertEqual(b"bar\n", tag.message)
self.assertLess(time.time() - tag.tag_time, 5)
tags = self.repo.refs.as_dict(b"refs/tags")
self.assertEqual(list(tags.keys()), [b"tryme"])
tag = self.repo[b"refs/tags/tryme"]
- self.assertTrue(isinstance(tag, Tag))
+ self.assertIsInstance(tag, Tag)
self.assertEqual(b"foo <foo@bar.com>", tag.tagger)
self.assertEqual(b"bar\n", tag.message)
self.assertLess(time.time() - tag.tag_time, 5)
[c1] = build_commit_graph(self.repo.object_store, [[1]])
self.repo[b"HEAD"] = c1.id
porcelain.tag_create(self.repo, b"foo")
- self.assertTrue(b"foo" in porcelain.tag_list(self.repo))
+ self.assertIn(b"foo", porcelain.tag_list(self.repo))
porcelain.tag_delete(self.repo, b"foo")
- self.assertFalse(b"foo" in porcelain.tag_list(self.repo))
+ self.assertNotIn(b"foo", porcelain.tag_list(self.repo))
class ResetTests(PorcelainTestCase):
outlines = outf.getvalue().splitlines()
self.assertEqual(
[
- b"0091319b56ce3aee2d489f759736a79cc552c9bb86d9 HEAD\x00 report-status " # noqa: E501
+ b"0091319b56ce3aee2d489f759736a79cc552c9bb86d9 HEAD\x00 report-status "
b"delete-refs quiet ofs-delta side-band-64k "
b"no-done symref=HEAD:refs/heads/master",
b"003f319b56ce3aee2d489f759736a79cc552c9bb86d9 refs/heads/master",
[c1] = build_commit_graph(self.repo.object_store, [[1]])
self.repo[b"HEAD"] = c1.id
porcelain.branch_create(self.repo, b"foo")
- self.assertTrue(b"foo" in porcelain.branch_list(self.repo))
+ self.assertIn(b"foo", porcelain.branch_list(self.repo))
porcelain.branch_delete(self.repo, b"foo")
- self.assertFalse(b"foo" in porcelain.branch_list(self.repo))
+ self.assertNotIn(b"foo", porcelain.branch_list(self.repo))
def test_simple_unicode(self):
[c1] = build_commit_graph(self.repo.object_store, [[1]])
self.repo[b"HEAD"] = c1.id
porcelain.branch_create(self.repo, "foo")
- self.assertTrue(b"foo" in porcelain.branch_list(self.repo))
+ self.assertIn(b"foo", porcelain.branch_list(self.repo))
porcelain.branch_delete(self.repo, "foo")
- self.assertFalse(b"foo" in porcelain.branch_list(self.repo))
+ self.assertNotIn(b"foo", porcelain.branch_list(self.repo))
class FetchTests(PorcelainTestCase):
committer=b"test2 <email>",
)
- self.assertFalse(self.repo[b"HEAD"].id in target_repo)
+ self.assertNotIn(self.repo[b"HEAD"].id, target_repo)
target_repo.close()
# Fetch changes into the cloned repo
# Check the target repo for pushed changes
with Repo(target_path) as r:
- self.assertTrue(self.repo[b"HEAD"].id in r)
+ self.assertIn(self.repo[b"HEAD"].id, r)
def test_with_remote_name(self):
remote_name = "origin"
committer=b"test2 <email>",
)
- self.assertFalse(self.repo[b"HEAD"].id in target_repo)
+ self.assertNotIn(self.repo[b"HEAD"].id, target_repo)
target_config = target_repo.get_config()
target_config.set(
# Check the target repo for pushed changes, as well as updates
# for the refs
with Repo(target_path) as r:
- self.assertTrue(self.repo[b"HEAD"].id in r)
+ self.assertIn(self.repo[b"HEAD"].id, r)
self.assertNotEqual(self.repo.get_refs(), target_refs)
def assert_correct_remote_refs(
class ActiveBranchTests(PorcelainTestCase):
def test_simple(self):
self.assertEqual(b"master", porcelain.active_branch(self.repo))
+
+
+class FindUniqueAbbrevTests(PorcelainTestCase):
+
+ def test_simple(self):
+ c1, c2, c3 = build_commit_graph(
+ self.repo.object_store, [[1], [2, 1], [3, 1, 2]]
+ )
+ self.repo.refs[b"HEAD"] = c3.id
+ self.assertEqual(
+ c1.id.decode('ascii')[:7],
+ porcelain.find_unique_abbrev(self.repo.object_store, c1.id))
blob - e5aefc0090760a9a2c519e9a0e25c8e8221c931e
blob + 6ad74c6c247e4be21331a85367dfc8747343fea2
--- dulwich/tests/test_refs.py
+++ dulwich/tests/test_refs.py
def test_set_symbolic_ref_overwrite(self):
nines = b"9" * 40
- self.assertFalse(b"refs/heads/symbolic" in self._refs)
+ self.assertNotIn(b"refs/heads/symbolic", self._refs)
self._refs[b"refs/heads/symbolic"] = nines
self.assertEqual(nines, self._refs.read_loose_ref(b"refs/heads/symbolic"))
self._refs.set_symbolic_ref(b"refs/heads/symbolic", b"refs/heads/master")
)
def test_contains(self):
- self.assertTrue(b"refs/heads/master" in self._refs)
- self.assertFalse(b"refs/heads/bar" in self._refs)
+ self.assertIn(b"refs/heads/master", self._refs)
+ self.assertNotIn(b"refs/heads/bar", self._refs)
def test_delitem(self):
self.assertEqual(
)
)
self.assertTrue(self._refs.remove_if_equals(b"refs/tags/refs-0.2", ZERO_SHA))
- self.assertFalse(b"refs/tags/refs-0.2" in self._refs)
+ self.assertNotIn(b"refs/tags/refs-0.2", self._refs)
def test_import_refs_name(self):
self._refs[
nines = b"9" * 40
self.assertEqual(b"ref: refs/heads/master", refs.read_ref(b"HEAD"))
- self.assertFalse(b"refs/heads/master" in refs)
+ self.assertNotIn(b"refs/heads/master", refs)
self.assertTrue(refs.add_if_new(b"HEAD", nines))
self.assertEqual(b"ref: refs/heads/master", refs.read_ref(b"HEAD"))
self.assertEqual(nines, refs[b"HEAD"])
RefsContainerTests.test_delitem(self)
ref_file = os.path.join(self._refs.path, b"refs", b"heads", b"master")
self.assertFalse(os.path.exists(ref_file))
- self.assertFalse(b"refs/heads/master" in self._refs.get_packed_refs())
+ self.assertNotIn(b"refs/heads/master", self._refs.get_packed_refs())
def test_delitem_symbolic(self):
self.assertEqual(b"ref: refs/heads/master", self._refs.read_loose_ref(b"HEAD"))
def test_contains(self):
refs = InfoRefsContainer(BytesIO(_TEST_REFS_SERIALIZED))
- self.assertTrue(b"refs/heads/master" in refs)
- self.assertFalse(b"refs/heads/bar" in refs)
+ self.assertIn(b"refs/heads/master", refs)
+ self.assertNotIn(b"refs/heads/bar", refs)
def test_get_peeled(self):
refs = InfoRefsContainer(BytesIO(_TEST_REFS_SERIALIZED))
blob - ee328013b16ac8a38bcb848a4eb1455d8453b1dd
blob + f22f5e41630931d817e697658b60699119fd3b6f
--- dulwich/tests/test_repository.py
+++ dulwich/tests/test_repository.py
barestr = b"bare = " + str(expect_bare).lower().encode("ascii")
with repo.get_named_file("config") as f:
config_text = f.read()
- self.assertTrue(barestr in config_text, "%r" % config_text)
+ self.assertIn(barestr, config_text, "%r" % config_text)
expect_filemode = sys.platform != "win32"
barestr = b"filemode = " + str(expect_filemode).lower().encode("ascii")
with repo.get_named_file("config") as f:
config_text = f.read()
- self.assertTrue(barestr in config_text, "%r" % config_text)
+ self.assertIn(barestr, config_text, "%r" % config_text)
if isinstance(repo, Repo):
expected_mode = '0o100644' if expect_filemode else '0o100666'
def test_contains_object(self):
r = self.open_repo("a.git")
- self.assertTrue(r.head() in r)
- self.assertFalse(b"z" * 40 in r)
+ self.assertIn(r.head(), r)
+ self.assertNotIn(b"z" * 40, r)
def test_contains_ref(self):
r = self.open_repo("a.git")
- self.assertTrue(b"HEAD" in r)
+ self.assertIn(b"HEAD", r)
def test_get_no_description(self):
r = self.open_repo("a.git")
def test_contains_missing(self):
r = self.open_repo("a.git")
- self.assertFalse(b"bar" in r)
+ self.assertNotIn(b"bar", r)
def test_get_peeled(self):
# unpacked ref
self.assertEqual(self._root_commit, r[b"HEAD"].id)
self.assertEqual(commit_sha, r[b"refs/heads/new_branch"].id)
self.assertEqual([], r[commit_sha].parents)
- self.assertTrue(b"refs/heads/new_branch" in r)
+ self.assertIn(b"refs/heads/new_branch", r)
new_branch_head = commit_sha
blob - 42ff04d12bd9ad06f1f28062778b8181dfa08ae8
blob + eec21133f84fd1917ec883d252aff5e234a403ba
--- dulwich/tests/test_server.py
+++ dulwich/tests/test_server.py
# ignore innocuous but unknown capabilities
self.assertRaises(GitProtocolError, set_caps, [b"cap2", b"ignoreme"])
- self.assertFalse(b"ignoreme" in self._handler.capabilities())
+ self.assertNotIn(b"ignoreme", self._handler.capabilities())
self._handler.innocuous_capabilities = lambda: (b"ignoreme",)
self.assertSucceeds(set_caps, [b"cap2", b"ignoreme"])
blob - a7dca5d6a42a0276d032014c9f4a2e50be3eb0b3
blob + 847ef5e2e8699091a40fe2d4219d1ea931be0294
--- dulwich/tests/test_utils.py
+++ dulwich/tests/test_utils.py
def test_linear(self):
c1, c2 = build_commit_graph(self.store, [[1], [2, 1]])
for obj_id in [c1.id, c2.id, c1.tree, c2.tree]:
- self.assertTrue(obj_id in self.store)
+ self.assertIn(obj_id, self.store)
self.assertEqual([], c1.parents)
self.assertEqual([c1.id], c2.parents)
self.assertEqual(c1.tree, c2.tree)
self.assertEqual([], self.store[c1.tree].items())
- self.assertTrue(c2.commit_time > c1.commit_time)
+ self.assertGreater(c2.commit_time, c1.commit_time)
def test_merge(self):
c1, c2, c3, c4 = build_commit_graph(
self.store, [[1], [2, 1], [3, 1], [4, 2, 3]]
)
self.assertEqual([c2.id, c3.id], c4.parents)
- self.assertTrue(c4.commit_time > c2.commit_time)
- self.assertTrue(c4.commit_time > c3.commit_time)
+ self.assertGreater(c4.commit_time, c2.commit_time)
+ self.assertGreater(c4.commit_time, c3.commit_time)
def test_missing_parent(self):
self.assertRaises(
blob - 6541c7c1e33d435c70209c774415c55352f5715e
blob + 34fcc545649a62719b7dabd344e9376f4a2a4b46
--- dulwich/tests/test_web.py
+++ dulwich/tests/test_web.py
return None
def assertContentTypeEquals(self, expected):
- self.assertTrue(("Content-Type", expected) in self._headers)
+ self.assertIn(("Content-Type", expected), self._headers)
def _test_backend(objects, refs=None, named_files=None):
mat = re.search(".*", "/git-evil-handler")
content = list(handle_service_request(self._req, "backend", mat))
self.assertEqual(HTTP_FORBIDDEN, self._status)
- self.assertFalse(b"git-evil-handler" in b"".join(content))
+ self.assertNotIn(b"git-evil-handler", b"".join(content))
self.assertFalse(self._req.cached)
def _run_handle_service_request(self, content_length=None):
mat = re.search(".*", "/git-evil-pack")
content = list(get_info_refs(self._req, Backend(), mat))
- self.assertFalse(b"git-evil-handler" in b"".join(content))
+ self.assertNotIn(b"git-evil-handler", b"".join(content))
self.assertEqual(HTTP_FORBIDDEN, self._status)
self.assertFalse(self._req.cached)
blob - 328b391352b8f9bda26597c78fde602a20065bf0
blob + 27ac8577ad6eb73a7fb204437a432ad9c37402e9
--- dulwich/web.py
+++ dulwich/web.py
class HTTPGitRequest(object):
"""Class encapsulating the state of a single git HTTP request.
- :ivar environ: the WSGI environment for the request.
+ Attributes:
+ environ: the WSGI environment for the request.
"""
def __init__(self, environ, start_response, dumb: bool = False, handlers=None):
class HTTPGitApplication(object):
"""Class encapsulating the state of a git WSGI application.
- :ivar backend: the Backend object backing this application
+ Attributes:
+ backend: the Backend object backing this application
"""
services = {
blob - 10989e70ddc37e59a0b546b680dcdbc375f5e454
blob + 898d25899cc09937c040d2f8c9a1e9fa914bee87
--- dulwich.egg-info/PKG-INFO
+++ dulwich.egg-info/PKG-INFO
Metadata-Version: 2.1
Name: dulwich
-Version: 0.20.31
+Version: 0.20.35
Summary: Python Git Library
Home-page: https://www.dulwich.io/
Author: Jelmer Vernooij
blob - cb1509bcd238b2846f70be01ca0e2cd58bfb5f67
blob + df6f41c058c8948945b84cd38845c17eb4f85c28
--- dulwich.egg-info/SOURCES.txt
+++ dulwich.egg-info/SOURCES.txt
dulwich/contrib/diffstat.py
dulwich/contrib/paramiko_vendor.py
dulwich/contrib/release_robot.py
+dulwich/contrib/requests_vendor.py
dulwich/contrib/swift.py
dulwich/contrib/test_paramiko_vendor.py
dulwich/contrib/test_release_robot.py
blob - 4d8177fc36e4b011df20e44ae387cdc9b50ec33e
blob + a838c1e971cd9c6f8916e4fe6ad026845900aaa5
--- releaser.conf
+++ releaser.conf
timeout_days: 5
tag_name: "dulwich-$VERSION"
verify_command: "flake8 && make check"
+github_url: "https://github.com/dulwich/dulwich"
update_version {
path: "setup.py"
match: "^dulwich_version_string = '(.*)'$"
blob - 5d4ab14a88f6589b45ef7675a38bb8c7dc836708
blob + c1eed47566a5bedae1bc21014b88862d3edb217f
--- setup.py
+++ setup.py
'For 2.7 support, please install a version prior to 0.20')
-dulwich_version_string = '0.20.31'
+dulwich_version_string = '0.20.35'
class DulwichDistribution(Distribution):