Skip to content

Commit

Permalink
add travis
Browse files Browse the repository at this point in the history
  • Loading branch information
Yobmod committed Jun 17, 2021
2 parents df39446 + 636f77b commit 3a84459
Show file tree
Hide file tree
Showing 13 changed files with 144 additions and 19 deletions.
46 changes: 46 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
# UNUSED, only for reference. If adjustments are needed, please see github actions
language: python
python:
<<<<<<< HEAD
- "3.4"
=======
>>>>>>> b0f79c58ad919e90261d1e332df79a4ad0bc40de
- "3.6"
- "3.7"
- "3.8"
- "nightly"
# - "pypy" - won't work as smmap doesn't work (see gitdb/.travis.yml for details)
matrix:
allow_failures:
- python: "nightly"
git:
# a higher depth is needed for most of the tests - must be high enough to not actually be shallow
# as we clone our own repository in the process
depth: 99999
install:
- python --version; git --version
- git submodule update --init --recursive
- git fetch --tags
- pip install -r test-requirements.txt
- pip install -r doc/requirements.txt
- pip install codecov

# generate some reflog as git-python tests need it (in master)
- ./init-tests-after-clone.sh

# as commits are performed with the default user, it needs to be set for travis too
- git config --global user.email "travis@ci.com"
- git config --global user.name "Travis Runner"
# If we rewrite the user's config by accident, we will mess it up
# and cause subsequent tests to fail
- cat git/test/fixtures/.gitconfig >> ~/.gitconfig
script:
# Make sure we limit open handles to see if we are leaking them
- ulimit -n 128
- ulimit -n
- coverage run --omit="test/*" -m unittest --buffer
- coverage report
- if [ "$TRAVIS_PYTHON_VERSION" == '3.6' ]; then cd doc && make html; fi
- if [ "$TRAVIS_PYTHON_VERSION" == '3.6' ]; then flake8 --ignore=W293,E265,E266,W503,W504,E731; fi
after_success:
- codecov
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,5 @@ Contributors are:
-Liam Beguin <liambeguin _at_ gmail.com>
-Ram Rachum <ram _at_ rachum.com>
-Alba Mendez <me _at_ alba.sh>
-Robert Westman <robert _at_ byteflux.io>
Portions derived from other open source works and are clearly marked.
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.1.17
3.1.18
8 changes: 8 additions & 0 deletions doc/source/changes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
Changelog
=========

3.1.18
======

* drop support for python 3.5 to reduce maintenance burden on typing. Lower patch levels of python 3.5 would break, too.

See the following for details:
https://github.com/gitpython-developers/gitpython/milestone/50?closed=1

3.1.17
======

Expand Down
9 changes: 0 additions & 9 deletions git/cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,7 @@
import subprocess
import sys
import threading
from collections import OrderedDict
from textwrap import dedent
import warnings

from git.compat import (
defenc,
Expand Down Expand Up @@ -1004,13 +1002,6 @@ def transform_kwarg(self, name: str, value: Any, split_single_char_options: bool

def transform_kwargs(self, split_single_char_options: bool = True, **kwargs: Any) -> List[str]:
"""Transforms Python style kwargs into git command line options."""
# Python 3.6 preserves the order of kwargs and thus has a stable
# order. For older versions sort the kwargs by the key to get a stable
# order.
if sys.version_info[:2] < (3, 6):
kwargs = OrderedDict(sorted(kwargs.items(), key=lambda x: x[0]))
warnings.warn("Python 3.5 support is deprecated and will be removed 2021-09-05.\n" +
"It does not preserve the order for key-word arguments and enforce lexical sorting instead.")
args = []
for k, v in kwargs.items():
if isinstance(v, (list, tuple)):
Expand Down
3 changes: 2 additions & 1 deletion git/index/fun.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
S_ISDIR,
S_IFMT,
S_IFREG,
S_IXUSR,
)
import subprocess

Expand Down Expand Up @@ -115,7 +116,7 @@ def stat_mode_to_index_mode(mode: int) -> int:
return S_IFLNK
if S_ISDIR(mode) or S_IFMT(mode) == S_IFGITLINK: # submodules
return S_IFGITLINK
return S_IFREG | 0o644 | (mode & 0o111) # blobs with or without executable bit
return S_IFREG | (mode & S_IXUSR and 0o755 or 0o644) # blobs with or without executable bit


def write_cache(entries: Sequence[Union[BaseIndexEntry, 'IndexEntry']], stream: IO[bytes],
Expand Down
3 changes: 2 additions & 1 deletion git/refs/tag.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ class TagReference(Reference):
print(tagref.tag.message)"""

__slots__ = ()
_common_path_default = "refs/tags"
_common_default = "tags"
_common_path_default = Reference._common_path_default + "/" + _common_default

@property
def commit(self):
Expand Down
2 changes: 1 addition & 1 deletion git/remote.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ def stale_refs(self) -> IterableList:
# * [would prune] origin/new_branch
token = " * [would prune] "
if not line.startswith(token):
raise ValueError("Could not parse git-remote prune result: %r" % line)
continue
ref_name = line.replace(token, "")
# sometimes, paths start with a full ref name, like refs/tags/foo, see #260
if ref_name.startswith(Reference._common_path_default + '/'):
Expand Down
32 changes: 30 additions & 2 deletions git/repo/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php

import logging
import os
import re
import warnings

from gitdb.exc import BadObject

from git.cmd import (
Git,
handle_process_output
Expand Down Expand Up @@ -402,7 +403,17 @@ def tags(self) -> 'IterableList':
def tag(self, path: PathLike) -> TagReference:
""":return: TagReference Object, reference pointing to a Commit or Tag
:param path: path to the tag reference, i.e. 0.1.5 or tags/0.1.5 """
return TagReference(self, path)
full_path = self._to_full_tag_path(path)
return TagReference(self, full_path)

@staticmethod
def _to_full_tag_path(path):
if path.startswith(TagReference._common_path_default + '/'):
return path
if path.startswith(TagReference._common_default + '/'):
return Reference._common_path_default + '/' + path
else:
return TagReference._common_path_default + '/' + path

def create_head(self, path: PathLike, commit: str = 'HEAD',
force: bool = False, logmsg: Optional[str] = None
Expand Down Expand Up @@ -608,6 +619,23 @@ def is_ancestor(self, ancestor_rev: 'Commit', rev: 'Commit') -> bool:
raise
return True

def is_valid_object(self, sha: str, object_type: str = None) -> bool:
try:
complete_sha = self.odb.partial_to_complete_sha_hex(sha)
object_info = self.odb.info(complete_sha)
if object_type:
if object_info.type == object_type.encode():
return True
else:
log.debug("Commit hash points to an object of type '%s'. Requested were objects of type '%s'",
object_info.type.decode(), object_type)
return False
else:
return True
except BadObject:
log.debug("Commit hash is invalid.")
return False

def _get_daemon_export(self) -> bool:
if self.git_dir:
filename = osp.join(self.git_dir, self.DAEMON_EXPORT_FILE)
Expand Down
2 changes: 1 addition & 1 deletion git/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,7 +470,7 @@ def _parse_progress_line(self, line: AnyStr) -> None:
line_str = line
self._cur_line = line_str

if self.error_lines or self._cur_line.startswith(('error:', 'fatal:')):
if self._cur_line.startswith(('error:', 'fatal:')):
self.error_lines.append(self._cur_line)
return

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,6 @@ def build_py_modules(basedir, excludes=[]):
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9"
"Programming Language :: Python :: 3.9"
]
)
15 changes: 13 additions & 2 deletions test/test_fun.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from io import BytesIO
from stat import S_IFDIR, S_IFREG, S_IFLNK
from stat import S_IFDIR, S_IFREG, S_IFLNK, S_IXUSR
from os import stat
import os.path as osp
from unittest import SkipTest

from git import Git
from git.index import IndexFile
from git.index.fun import (
aggressive_tree_merge
aggressive_tree_merge,
stat_mode_to_index_mode,
)
from git.objects.fun import (
traverse_tree_recursive,
Expand Down Expand Up @@ -206,6 +207,16 @@ def assert_entries(entries, num_entries, has_conflict=False):
assert_entries(aggressive_tree_merge(odb, trees), 2, True)
# END handle ours, theirs

def test_stat_mode_to_index_mode(self):
modes = (
0o600, 0o611, 0o640, 0o641, 0o644, 0o650, 0o651,
0o700, 0o711, 0o740, 0o744, 0o750, 0o751, 0o755,
)
for mode in modes:
expected_mode = S_IFREG | (mode & S_IXUSR and 0o755 or 0o644)
assert stat_mode_to_index_mode(mode) == expected_mode
# END for each mode

def _assert_tree_entries(self, entries, num_trees):
for entry in entries:
assert len(entry) == num_trees
Expand Down
38 changes: 38 additions & 0 deletions test/test_repo.py
Original file line number Diff line number Diff line change
Expand Up @@ -414,6 +414,16 @@ def test_index(self):
def test_tag(self):
assert self.rorepo.tag('refs/tags/0.1.5').commit

def test_tag_to_full_tag_path(self):
tags = ['0.1.5', 'tags/0.1.5', 'refs/tags/0.1.5']
value_errors = []
for tag in tags:
try:
self.rorepo.tag(tag)
except ValueError as valueError:
value_errors.append(valueError.args[0])
self.assertEqual(value_errors, [])

def test_archive(self):
tmpfile = tempfile.mktemp(suffix='archive-test')
with open(tmpfile, 'wb') as stream:
Expand Down Expand Up @@ -979,6 +989,34 @@ def test_is_ancestor(self):
for i, j in itertools.permutations([c1, 'ffffff', ''], r=2):
self.assertRaises(GitCommandError, repo.is_ancestor, i, j)

def test_is_valid_object(self):
repo = self.rorepo
commit_sha = 'f6aa8d1'
blob_sha = '1fbe3e4375'
tree_sha = '960b40fe36'
tag_sha = '42c2f60c43'

# Check for valid objects
self.assertTrue(repo.is_valid_object(commit_sha))
self.assertTrue(repo.is_valid_object(blob_sha))
self.assertTrue(repo.is_valid_object(tree_sha))
self.assertTrue(repo.is_valid_object(tag_sha))

# Check for valid objects of specific type
self.assertTrue(repo.is_valid_object(commit_sha, 'commit'))
self.assertTrue(repo.is_valid_object(blob_sha, 'blob'))
self.assertTrue(repo.is_valid_object(tree_sha, 'tree'))
self.assertTrue(repo.is_valid_object(tag_sha, 'tag'))

# Check for invalid objects
self.assertFalse(repo.is_valid_object(b'1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a1a', 'blob'))

# Check for invalid objects of specific type
self.assertFalse(repo.is_valid_object(commit_sha, 'blob'))
self.assertFalse(repo.is_valid_object(blob_sha, 'commit'))
self.assertFalse(repo.is_valid_object(tree_sha, 'commit'))
self.assertFalse(repo.is_valid_object(tag_sha, 'commit'))

@with_rw_directory
def test_git_work_tree_dotgit(self, rw_dir):
"""Check that we find .git as a worktree file and find the worktree
Expand Down

0 comments on commit 3a84459

Please sign in to comment.