Compare commits
156 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
371c97cadb | ||
![]() |
ab3bb01249 | ||
![]() |
62c70e852d | ||
![]() |
e81f45c4c6 | ||
![]() |
295166bb64 | ||
![]() |
96d37e16a9 | ||
![]() |
2ce8b952c4 | ||
![]() |
e41f71f458 | ||
![]() |
c6305a062b | ||
![]() |
87beb76dcc | ||
![]() |
f18de427bf | ||
![]() |
f841c62fa6 | ||
![]() |
035d4a9396 | ||
![]() |
21d668421f | ||
![]() |
b88dc86842 | ||
![]() |
8559b2da20 | ||
![]() |
9325494d6f | ||
![]() |
74717bed55 | ||
![]() |
3818555e14 | ||
![]() |
706c60c4ab | ||
![]() |
0733ba4da3 | ||
![]() |
320ee5e733 | ||
![]() |
d6716e035a | ||
![]() |
d14438725e | ||
![]() |
dd57c9b366 | ||
![]() |
f2c89a760a | ||
![]() |
f37cf25b8e | ||
![]() |
11ff7a99eb | ||
![]() |
9335819795 | ||
![]() |
784583d21e | ||
![]() |
b81810e9cb | ||
![]() |
7ee851273a | ||
![]() |
1fadc2eae0 | ||
![]() |
453fd8a9a3 | ||
![]() |
630d905e73 | ||
![]() |
9be907983f | ||
![]() |
b31ac50210 | ||
![]() |
da233b16c5 | ||
![]() |
1a842ff8bd | ||
![]() |
cbbf9f1f87 | ||
![]() |
a294655aa5 | ||
![]() |
5a940987cd | ||
![]() |
354d56a95c | ||
![]() |
8327e1bee3 | ||
![]() |
15326b731f | ||
![]() |
f5cd6da307 | ||
![]() |
803b1cb154 | ||
![]() |
d622e87654 | ||
![]() |
819cbff552 | ||
![]() |
4fbc1f1c05 | ||
![]() |
5c061cbb0a | ||
![]() |
68817aad4f | ||
![]() |
0b513d57fa | ||
![]() |
074a726d7f | ||
![]() |
950249442e | ||
![]() |
809fe33b8a | ||
![]() |
6402302002 | ||
![]() |
77f0585645 | ||
![]() |
acdec78617 | ||
![]() |
66280af83a | ||
![]() |
b2a34bd901 | ||
![]() |
44ef9ad2e9 | ||
![]() |
db213113f4 | ||
![]() |
ee28de65a0 | ||
![]() |
825f3e45bd | ||
![]() |
00dd78bf1b | ||
![]() |
e2393a5e24 | ||
![]() |
da59cb1c92 | ||
![]() |
e873c6a363 | ||
![]() |
865c2f0e82 | ||
![]() |
6d6931cd26 | ||
![]() |
9b364dc7f3 | ||
![]() |
578cf58cd7 | ||
![]() |
554f167353 | ||
![]() |
54e4da837b | ||
![]() |
faf6a63d25 | ||
![]() |
30980751cf | ||
![]() |
dae61ded38 | ||
![]() |
0e270c72bd | ||
![]() |
1afbde0d7f | ||
![]() |
7fe7a4da8d | ||
![]() |
fd1e9e3d35 | ||
![]() |
cdd57b2c0f | ||
![]() |
ffc514fa24 | ||
![]() |
c57a3aeb22 | ||
![]() |
ca444f3c7d | ||
![]() |
96beae5c82 | ||
![]() |
68de0f8bb6 | ||
![]() |
df53551cb2 | ||
![]() |
5864b17b57 | ||
![]() |
6c4fa88d07 | ||
![]() |
e96d0286b8 | ||
![]() |
4fa43e234e | ||
![]() |
4416f65fe1 | ||
![]() |
5dcc793aff | ||
![]() |
30f539ff35 | ||
![]() |
df30f9213f | ||
![]() |
50c0569cf0 | ||
![]() |
d8fd2e78d8 | ||
![]() |
fd9a39a91b | ||
![]() |
270dad8cd3 | ||
![]() |
51915ddf0e | ||
![]() |
f2864c0511 | ||
![]() |
456bf59a88 | ||
![]() |
22021c67fc | ||
![]() |
c1d831c98a | ||
![]() |
391a3a74e9 | ||
![]() |
141f0abe62 | ||
![]() |
6b926494db | ||
![]() |
cde5b5170b | ||
![]() |
735510f14d | ||
![]() |
bc424e342f | ||
![]() |
3470fbc1c6 | ||
![]() |
487fb5913e | ||
![]() |
33cf1a1ca2 | ||
![]() |
95ad6b1b0a | ||
![]() |
fa60e2233d | ||
![]() |
daff45f2d4 | ||
![]() |
a5cfea21a7 | ||
![]() |
99dfce9ab8 | ||
![]() |
7a8474cd44 | ||
![]() |
91bb93d266 | ||
![]() |
13f4ddec1d | ||
![]() |
f92d38e25f | ||
![]() |
70edbf256a | ||
![]() |
203335bd63 | ||
![]() |
64150d3535 | ||
![]() |
d25a0d61de | ||
![]() |
f5aa1829ac | ||
![]() |
9db8737364 | ||
![]() |
cf439e4286 | ||
![]() |
eadc2a320f | ||
![]() |
2b083a1509 | ||
![]() |
681c7d4341 | ||
![]() |
8a66da1278 | ||
![]() |
0d2bc05708 | ||
![]() |
b8e6852d26 | ||
![]() |
563cb9018e | ||
![]() |
ac2e363d04 | ||
![]() |
ab97c08f72 | ||
![]() |
7b97ade6ce | ||
![]() |
e4ef8ea5c2 | ||
![]() |
50f4b20e7d | ||
![]() |
802976535a | ||
![]() |
ade211de60 | ||
![]() |
8911416d4f | ||
![]() |
4b607b8256 | ||
![]() |
ec23762c09 | ||
![]() |
ac7738bbb3 | ||
![]() |
29a8dbc6b2 | ||
![]() |
f28a199351 | ||
![]() |
becc265c78 | ||
![]() |
25d02259df | ||
![]() |
38b1975991 | ||
![]() |
9cce003efe | ||
![]() |
78d134c016 |
.gitignore.mailmap.travis.sh.travis.ymlCHANGELOG.rstREADME.rstappveyor.yml
docs
backends.rstconf.pydevelopment.rstdiff.rstgeneral.rstindex.rstinstall.rstobjects.rst
recipes
references.rstremotes.rstrepository.rstsubmodule.rstworking-copy.rstpygit2
__init__.py_build.py_run.pyblame.pyconfig.pycredentials.pydecl.herrors.pyffi.pyindex.pypy2.pypy3.pyrefspec.pyremote.pyrepository.pysettings.pysubmodule.pyutils.py
setup.pysrc
blob.cblob.hbranch.cbranch.hcommit.ccommit.hdiff.cdiff.herror.cerror.hnote.cnote.hobject.cobject.hoid.coid.hoptions.coptions.hpatch.cpatch.hpygit2.creference.creference.hrepository.crepository.hsignature.csignature.htag.ctag.htree.ctree.htreebuilder.ctreebuilder.htypes.hutils.cutils.hwalker.cwalker.h
test
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,6 +3,7 @@ build
|
||||
dist
|
||||
pygit2.so
|
||||
_pygit2.so
|
||||
.tox/
|
||||
test/*.pyc
|
||||
test/__pycache__
|
||||
pygit2/*.pyc
|
||||
|
8
.mailmap
8
.mailmap
@ -18,3 +18,11 @@ Vlad Temian <vladtemian@gmail.com>
|
||||
Matthew Gamble <git@matthewgamble.net>
|
||||
|
||||
Kaarel Kitsemets <kitsemets@gmail.com>
|
||||
|
||||
Matthias Bartelmeß <mba@fourplusone.de>
|
||||
Robert Hölzl <robert.hoelzl@posteo.de>
|
||||
Anatoly Techtonik <techtonik@gmail.com>
|
||||
|
||||
Guillermo Pérez <bisho@fb.com> <bisho@freedreams.org>
|
||||
Matthew Duggan <mduggan@qti.qualcomm.com> <mgithub@guarana.org>
|
||||
Alexander Bayandin <a.bayandin@gmail.com> <bayandin@users.noreply.github.com>
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
cd ~
|
||||
|
||||
git clone --depth=1 -b maint/v0.23 https://github.com/libgit2/libgit2.git
|
||||
git clone --depth=1 -b maint/v0.26 https://github.com/libgit2/libgit2.git
|
||||
cd libgit2/
|
||||
|
||||
mkdir build && cd build
|
||||
|
@ -2,11 +2,12 @@ language: python
|
||||
|
||||
python:
|
||||
- "2.7"
|
||||
- "3.2"
|
||||
- "3.3"
|
||||
- "3.4"
|
||||
- "3.5"
|
||||
- "3.6"
|
||||
- "pypy"
|
||||
- "pypy3"
|
||||
# - "pypy3"
|
||||
|
||||
env: LIBGIT2=~/libgit2/_install/ LD_LIBRARY_PATH=~/libgit2/_install/lib
|
||||
|
||||
|
859
CHANGELOG.rst
Normal file
859
CHANGELOG.rst
Normal file
@ -0,0 +1,859 @@
|
||||
0.26.0 (2017-07-06)
|
||||
-------------------------
|
||||
|
||||
- Update to libgit2 v0.26
|
||||
`#713 <https://github.com/libgit2/pygit2/pull/713>`_
|
||||
|
||||
- Drop support for Python 3.2, add support for cffi 1.10
|
||||
`#706 <https://github.com/libgit2/pygit2/pull/706>`_
|
||||
`#694 <https://github.com/libgit2/pygit2/issues/694>`_
|
||||
|
||||
- New ``Repository.revert_commit(...)``
|
||||
`#711 <https://github.com/libgit2/pygit2/pull/711>`_
|
||||
`#710 <https://github.com/libgit2/pygit2/issues/710>`_
|
||||
|
||||
- New ``Branch.is_checked_out()``
|
||||
`#696 <https://github.com/libgit2/pygit2/pull/696>`_
|
||||
|
||||
- Various fixes
|
||||
`#706 <https://github.com/libgit2/pygit2/pull/706>`_
|
||||
`#707 <https://github.com/libgit2/pygit2/pull/707>`_
|
||||
`#708 <https://github.com/libgit2/pygit2/pull/708>`_
|
||||
|
||||
|
||||
0.25.1 (2017-04-25)
|
||||
-------------------------
|
||||
|
||||
- Add suport for Python 3.6
|
||||
|
||||
- New support for stash: repository methods ``stash``, ``stash_apply``,
|
||||
``stash_drop`` and ``stash_pop``
|
||||
`#695 <https://github.com/libgit2/pygit2/pull/695>`_
|
||||
|
||||
- Improved support for submodules: new repository methods ``init_submodules``
|
||||
and ``update_submodules``
|
||||
`#692 <https://github.com/libgit2/pygit2/pull/692>`_
|
||||
|
||||
- New friendlier API for branches & references: ``Repository.branches`` and
|
||||
``Repository.references``
|
||||
`#700 <https://github.com/libgit2/pygit2/pull/700>`_
|
||||
`#701 <https://github.com/libgit2/pygit2/pull/701>`_
|
||||
|
||||
- New support for custom backends
|
||||
`#690 <https://github.com/libgit2/pygit2/pull/690>`_
|
||||
|
||||
- Fix ``init_repository`` crash on None input
|
||||
`#688 <https://github.com/libgit2/pygit2/issues/688>`_
|
||||
`#697 <https://github.com/libgit2/pygit2/pull/697>`_
|
||||
|
||||
- Fix checkout with an orphan master branch
|
||||
`#669 <https://github.com/libgit2/pygit2/issues/669>`_
|
||||
`#685 <https://github.com/libgit2/pygit2/pull/685>`_
|
||||
|
||||
- Better error messages for opening repositories
|
||||
`#645 <https://github.com/libgit2/pygit2/issues/645>`_
|
||||
`#698 <https://github.com/libgit2/pygit2/pull/698>`_
|
||||
|
||||
|
||||
0.25.0 (2016-12-26)
|
||||
-------------------------
|
||||
|
||||
- Upgrade to libgit2 0.25
|
||||
`#670 <https://github.com/libgit2/pygit2/pull/670>`_
|
||||
|
||||
- Now Commit.tree raises an error if tree is not found
|
||||
`#682 <https://github.com/libgit2/pygit2/pull/682>`_
|
||||
|
||||
- New settings.mwindow_mapped_limit, cached_memory, enable_caching,
|
||||
cache_max_size and cache_object_limit
|
||||
`#677 <https://github.com/libgit2/pygit2/pull/677>`_
|
||||
|
||||
|
||||
0.24.2 (2016-11-01)
|
||||
-------------------------
|
||||
|
||||
- Unit tests pass on Windows, integration with AppVeyor
|
||||
`#641 <https://github.com/libgit2/pygit2/pull/641>`_
|
||||
`#655 <https://github.com/libgit2/pygit2/issues/655>`_
|
||||
`#657 <https://github.com/libgit2/pygit2/pull/657>`_
|
||||
`#659 <https://github.com/libgit2/pygit2/pull/659>`_
|
||||
`#660 <https://github.com/libgit2/pygit2/pull/660>`_
|
||||
`#661 <https://github.com/libgit2/pygit2/pull/661>`_
|
||||
`#667 <https://github.com/libgit2/pygit2/pull/667>`_
|
||||
|
||||
- Fix when libgit2 error messages have non-ascii chars
|
||||
`#651 <https://github.com/libgit2/pygit2/pull/651>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#643 <https://github.com/libgit2/pygit2/pull/643>`_
|
||||
`#653 <https://github.com/libgit2/pygit2/pull/653>`_
|
||||
`#663 <https://github.com/libgit2/pygit2/pull/663>`_
|
||||
|
||||
|
||||
0.24.1 (2016-06-21)
|
||||
-------------------------
|
||||
|
||||
- New ``Repository.listall_reference_objects()``
|
||||
`#634 <https://github.com/libgit2/pygit2/pull/634>`_
|
||||
|
||||
- Fix ``Repository.write_archive(...)``
|
||||
`#619 <https://github.com/libgit2/pygit2/pull/619>`_
|
||||
`#621 <https://github.com/libgit2/pygit2/pull/621>`_
|
||||
|
||||
- Reproducible builds
|
||||
`#636 <https://github.com/libgit2/pygit2/pull/636>`_
|
||||
|
||||
- Documentation fixes
|
||||
`#606 <https://github.com/libgit2/pygit2/pull/606>`_
|
||||
`#607 <https://github.com/libgit2/pygit2/pull/607>`_
|
||||
`#609 <https://github.com/libgit2/pygit2/pull/609>`_
|
||||
`#623 <https://github.com/libgit2/pygit2/pull/623>`_
|
||||
|
||||
- Test updates
|
||||
`#629 <https://github.com/libgit2/pygit2/pull/629>`_
|
||||
|
||||
|
||||
0.24.0 (2016-03-05)
|
||||
-------------------------
|
||||
|
||||
- Update to libgit2 v0.24
|
||||
`#594 <https://github.com/libgit2/pygit2/pull/594>`_
|
||||
|
||||
- Support Python 3.5
|
||||
|
||||
- New dependency, `six <https://pypi.python.org/pypi/six/>`_
|
||||
|
||||
- New ``Repository.path_is_ignored(path)``
|
||||
`#589 <https://github.com/libgit2/pygit2/pull/589>`_
|
||||
|
||||
- Fix error in ``Repository(path)`` when path is a bytes string
|
||||
`#588 <https://github.com/libgit2/pygit2/issues/588>`_
|
||||
`#593 <https://github.com/libgit2/pygit2/pull/593>`_
|
||||
|
||||
- Fix memory issue in ``Repository.describe(...)``
|
||||
`#592 <https://github.com/libgit2/pygit2/issues/592>`_
|
||||
`#597 <https://github.com/libgit2/pygit2/issues/597>`_
|
||||
`#599 <https://github.com/libgit2/pygit2/pull/599>`_
|
||||
|
||||
- Allow testing with `tox <https://pypi.python.org/pypi/tox/>`_
|
||||
`#600 <https://github.com/libgit2/pygit2/pull/600>`_
|
||||
|
||||
|
||||
0.23.3 (2016-01-01)
|
||||
-------------------------
|
||||
|
||||
- New ``Repository.create_blob_fromiobase(...)``
|
||||
`#490 <https://github.com/libgit2/pygit2/pull/490>`_
|
||||
`#577 <https://github.com/libgit2/pygit2/pull/577>`_
|
||||
|
||||
- New ``Repository.describe(...)``
|
||||
`#585 <https://github.com/libgit2/pygit2/pull/585>`_
|
||||
|
||||
- Fix ``Signature`` default encoding, UTF-8 now
|
||||
`#581 <https://github.com/libgit2/pygit2/issues/581>`_
|
||||
|
||||
- Fixing ``pip install pygit2``, should install cffi first
|
||||
|
||||
- Unit tests, fix binary diff test
|
||||
`#586 <https://github.com/libgit2/pygit2/pull/586>`_
|
||||
|
||||
- Document that ``Diff.patch`` can be ``None``
|
||||
`#587 <https://github.com/libgit2/pygit2/pull/587>`_
|
||||
|
||||
|
||||
0.23.2 (2015-10-11)
|
||||
-------------------------
|
||||
|
||||
- Unify callbacks system for remotes and clone
|
||||
`#568 <https://github.com/libgit2/pygit2/pull/568>`_
|
||||
|
||||
- New ``TreeEntry._name``
|
||||
`#570 <https://github.com/libgit2/pygit2/pull/570>`_
|
||||
|
||||
- Fix segfault in ``Tag._message``
|
||||
`#572 <https://github.com/libgit2/pygit2/pull/572>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#569 <https://github.com/libgit2/pygit2/pull/569>`_
|
||||
`#574 <https://github.com/libgit2/pygit2/pull/574>`_
|
||||
|
||||
API changes to clone::
|
||||
|
||||
# Before
|
||||
clone_repository(..., credentials, certificate)
|
||||
|
||||
# Now
|
||||
callbacks = RemoteCallbacks(credentials, certificate)
|
||||
clone_repository(..., callbacks)
|
||||
|
||||
API changes to remote::
|
||||
|
||||
# Before
|
||||
def transfer_progress(stats):
|
||||
...
|
||||
|
||||
remote.credentials = credentials
|
||||
remote.transfer_progress = transfer_progress
|
||||
remote.fetch()
|
||||
remote.push(specs)
|
||||
|
||||
# Now
|
||||
class MyCallbacks(RemoteCallbacks):
|
||||
def transfer_progress(self, stats):
|
||||
...
|
||||
|
||||
callbacks = MyCallbacks(credentials)
|
||||
remote.fetch(callbacks=callbacks)
|
||||
remote.push(specs, callbacks=callbacks)
|
||||
|
||||
|
||||
0.23.1 (2015-09-26)
|
||||
-------------------------
|
||||
|
||||
- Improve support for cffi 1.0+
|
||||
`#529 <https://github.com/libgit2/pygit2/pull/529>`_
|
||||
`#561 <https://github.com/libgit2/pygit2/pull/561>`_
|
||||
|
||||
- Fix ``Remote.push``
|
||||
`#557 <https://github.com/libgit2/pygit2/pull/557>`_
|
||||
|
||||
- New ``TreeEntry.type``
|
||||
`#560 <https://github.com/libgit2/pygit2/pull/560>`_
|
||||
|
||||
- New ``pygit2.GIT_DIFF_SHOW_BINARY``
|
||||
`#566 <https://github.com/libgit2/pygit2/pull/566>`_
|
||||
|
||||
|
||||
0.23.0 (2015-08-14)
|
||||
-------------------------
|
||||
|
||||
- Update to libgit2 v0.23
|
||||
`#540 <https://github.com/libgit2/pygit2/pull/540>`_
|
||||
|
||||
- Now ``Repository.merge_base(...)`` returns ``None`` if no merge base is found
|
||||
`#550 <https://github.com/libgit2/pygit2/pull/550>`_
|
||||
|
||||
- Documentation updates
|
||||
`#547 <https://github.com/libgit2/pygit2/pull/547>`_
|
||||
|
||||
API changes:
|
||||
|
||||
- How to set identity (aka signature) in a reflog has changed::
|
||||
|
||||
# Before
|
||||
signature = Signature('foo', 'bar')
|
||||
...
|
||||
reference.set_target(target, signature=signature, message=message)
|
||||
repo.set_head(target, signature=signature)
|
||||
remote.fetch(signature=signature)
|
||||
remote.push(signature=signature)
|
||||
|
||||
# Now
|
||||
repo.set_ident('foo', 'bar')
|
||||
...
|
||||
reference.set_target(target, message=message)
|
||||
repo.set_head(target)
|
||||
remote.push()
|
||||
|
||||
# The current identity can be get with
|
||||
repo.ident
|
||||
|
||||
- Some remote setters have been replaced by methods::
|
||||
|
||||
# Before # Now
|
||||
Remote.url = url Repository.remotes.set_url(name, url)
|
||||
Remote.push_url = url Repository.remotes.set_push_url(name, url)
|
||||
|
||||
Remote.add_fetch(refspec) Repository.remotes.add_fetch(name, refspec)
|
||||
Remote.add_push(refspec) Repository.remotes.add_push(name, refspec)
|
||||
|
||||
Remote.fetch_refspecs = [...] removed, use the config API instead
|
||||
Remote.push_refspecs = [...] removed, use the config API instead
|
||||
|
||||
|
||||
0.22.1 (2015-07-12)
|
||||
-------------------------
|
||||
|
||||
Diff interface refactoring
|
||||
`#346 <https://github.com/libgit2/pygit2/pull/346>`_
|
||||
(in progress):
|
||||
|
||||
- New ``iter(pygit2.Blame)``
|
||||
|
||||
- New ``pygit2.DiffDelta``, ``pygit2.DiffFile`` and ``pygit.DiffLine``
|
||||
|
||||
- API changes, translation table::
|
||||
|
||||
Hunk => DiffHunk
|
||||
Patch.old_file_path => Patch.delta.old_file.path
|
||||
Patch.new_file_path => Patch.delta.new_file.path
|
||||
Patch.old_id => Patch.delta.old_file.id
|
||||
Patch.new_id => Patch.delta.new_file.id
|
||||
Patch.status => Patch.delta.status
|
||||
Patch.similarity => Patch.delta.similarity
|
||||
Patch.is_binary => Patch.delta.is_binary
|
||||
Patch.additions => Patch.line_stats[1]
|
||||
Patch.deletions => Patch.line_stats[2]
|
||||
|
||||
- ``DiffHunk.lines`` is now a list of ``DiffLine`` objects, not tuples
|
||||
|
||||
New features:
|
||||
|
||||
- New ``Repository.expand_id(...)`` and ``Repository.ahead_behind(...)``
|
||||
`#448 <https://github.com/libgit2/pygit2/pull/448>`_
|
||||
|
||||
- New ``prefix`` parameter in ``Repository.write_archive``
|
||||
`#481 <https://github.com/libgit2/pygit2/pull/481>`_
|
||||
|
||||
- New ``Repository.merge_trees(...)``
|
||||
`#489 <https://github.com/libgit2/pygit2/pull/489>`_
|
||||
|
||||
- New ``Repository.cherrypick(...)``
|
||||
`#436 <https://github.com/libgit2/pygit2/issues/436>`_
|
||||
`#492 <https://github.com/libgit2/pygit2/pull/492>`_
|
||||
|
||||
- New support for submodules
|
||||
`#499 <https://github.com/libgit2/pygit2/pull/499>`_
|
||||
`#514 <https://github.com/libgit2/pygit2/pull/514>`_
|
||||
|
||||
- New ``Repository.merge_file_from_index(...)``
|
||||
`#503 <https://github.com/libgit2/pygit2/pull/503>`_
|
||||
|
||||
- Now ``Repository.diff`` supports diffing two blobs
|
||||
`#508 <https://github.com/libgit2/pygit2/pull/508>`_
|
||||
|
||||
- New optional ``fetch`` parameter in ``Remote.create``
|
||||
`#526 <https://github.com/libgit2/pygit2/pull/526>`_
|
||||
|
||||
- New ``pygit2.DiffStats``
|
||||
`#406 <https://github.com/libgit2/pygit2/issues/406>`_
|
||||
`#525 <https://github.com/libgit2/pygit2/pull/525>`_
|
||||
|
||||
- New ``Repository.get_attr(...)``
|
||||
`#528 <https://github.com/libgit2/pygit2/pull/528>`_
|
||||
|
||||
- New ``level`` optional parameter in ``Index.remove``
|
||||
`#533 <https://github.com/libgit2/pygit2/pull/533>`_
|
||||
|
||||
- New ``repr(TreeEntry)``
|
||||
`#543 <https://github.com/libgit2/pygit2/pull/543>`_
|
||||
|
||||
Build and install improvements:
|
||||
|
||||
- Make pygit work in a frozen environment
|
||||
`#453 <https://github.com/libgit2/pygit2/pull/453>`_
|
||||
|
||||
- Make pygit2 work with pyinstaller
|
||||
`#510 <https://github.com/libgit2/pygit2/pull/510>`_
|
||||
|
||||
Bugs fixed:
|
||||
|
||||
- Fix memory issues
|
||||
`#477 <https://github.com/libgit2/pygit2/issues/477>`_
|
||||
`#487 <https://github.com/libgit2/pygit2/pull/487>`_
|
||||
`#520 <https://github.com/libgit2/pygit2/pull/520>`_
|
||||
|
||||
- Fix TreeEntry equality testing
|
||||
`#458 <https://github.com/libgit2/pygit2/issues/458>`_
|
||||
`#488 <https://github.com/libgit2/pygit2/pull/488>`_
|
||||
|
||||
- ``Repository.write_archive`` fix handling of symlinks
|
||||
`#480 <https://github.com/libgit2/pygit2/pull/480>`_
|
||||
|
||||
- Fix type check in ``Diff[...]``
|
||||
`#495 <https://github.com/libgit2/pygit2/issues/495>`_
|
||||
|
||||
- Fix error when merging files with unicode content
|
||||
`#505 <https://github.com/libgit2/pygit2/pull/505>`_
|
||||
|
||||
Other:
|
||||
|
||||
- Documentation improvements and fixes
|
||||
`#448 <https://github.com/libgit2/pygit2/pull/448>`_
|
||||
`#491 <https://github.com/libgit2/pygit2/pull/491>`_
|
||||
`#497 <https://github.com/libgit2/pygit2/pull/497>`_
|
||||
`#507 <https://github.com/libgit2/pygit2/pull/507>`_
|
||||
`#517 <https://github.com/libgit2/pygit2/pull/517>`_
|
||||
`#518 <https://github.com/libgit2/pygit2/pull/518>`_
|
||||
`#519 <https://github.com/libgit2/pygit2/pull/519>`_
|
||||
`#521 <https://github.com/libgit2/pygit2/pull/521>`_
|
||||
`#523 <https://github.com/libgit2/pygit2/pull/523>`_
|
||||
`#527 <https://github.com/libgit2/pygit2/pull/527>`_
|
||||
`#536 <https://github.com/libgit2/pygit2/pull/536>`_
|
||||
|
||||
- Expose the ``pygit2.GIT_REPOSITORY_INIT_*`` constants
|
||||
`#483 <https://github.com/libgit2/pygit2/issues/483>`_
|
||||
|
||||
|
||||
0.22.0 (2015-01-16)
|
||||
-------------------
|
||||
|
||||
New:
|
||||
|
||||
- Update to libgit2 v0.22
|
||||
`#459 <https://github.com/libgit2/pygit2/pull/459>`_
|
||||
|
||||
- Add support for libgit2 feature detection
|
||||
(new ``pygit2.features`` and ``pygit2.GIT_FEATURE_*``)
|
||||
`#475 <https://github.com/libgit2/pygit2/pull/475>`_
|
||||
|
||||
- New ``Repository.remotes`` (``RemoteCollection``)
|
||||
`#447 <https://github.com/libgit2/pygit2/pull/447>`_
|
||||
|
||||
API Changes:
|
||||
|
||||
- Prototype of ``clone_repository`` changed, check documentation
|
||||
|
||||
- Removed ``clone_into``, use ``clone_repository`` with callbacks instead
|
||||
|
||||
- Use ``Repository.remotes.rename(name, new_name)`` instead of
|
||||
``Remote.rename(new_name)``
|
||||
|
||||
- Use ``Repository.remotes.delete(name)`` instead of ``Remote.delete()``
|
||||
|
||||
- Now ``Remote.push(...)`` takes a list of refspecs instead of just one
|
||||
|
||||
- Change ``Patch.old_id``, ``Patch.new_id``, ``Note.annotated_id``,
|
||||
``RefLogEntry.oid_old`` and ``RefLogEntry.oid_new`` to be ``Oid`` objects
|
||||
instead of strings
|
||||
`#449 <https://github.com/libgit2/pygit2/pull/449>`_
|
||||
|
||||
Other:
|
||||
|
||||
- Fix ``init_repository`` when passing optional parameters ``workdir_path``,
|
||||
``description``, ``template_path``, ``initial_head`` or ``origin_url``
|
||||
`#466 <https://github.com/libgit2/pygit2/issues/466>`_
|
||||
`#471 <https://github.com/libgit2/pygit2/pull/471>`_
|
||||
|
||||
- Fix use-after-free when patch outlives diff
|
||||
`#457 <https://github.com/libgit2/pygit2/issues/457>`_
|
||||
`#461 <https://github.com/libgit2/pygit2/pull/461>`_
|
||||
`#474 <https://github.com/libgit2/pygit2/pull/474>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#456 <https://github.com/libgit2/pygit2/issues/456>`_
|
||||
`#462 <https://github.com/libgit2/pygit2/pull/462>`_
|
||||
`#465 <https://github.com/libgit2/pygit2/pull/465>`_
|
||||
`#472 <https://github.com/libgit2/pygit2/pull/472>`_
|
||||
`#473 <https://github.com/libgit2/pygit2/pull/473>`_
|
||||
|
||||
- Make the GPL exception explicit in setup.py
|
||||
`#450 <https://github.com/libgit2/pygit2/pull/450>`_
|
||||
|
||||
|
||||
0.21.4 (2014-11-04)
|
||||
-------------------
|
||||
|
||||
- Fix credentials callback not set when pushing
|
||||
`#431 <https://github.com/libgit2/pygit2/pull/431>`_
|
||||
`#435 <https://github.com/libgit2/pygit2/issues/435>`_
|
||||
`#437 <https://github.com/libgit2/pygit2/issues/437>`_
|
||||
`#438 <https://github.com/libgit2/pygit2/pull/438>`_
|
||||
|
||||
- Fix ``Repository.diff(...)`` when treeish is "empty"
|
||||
`#432 <https://github.com/libgit2/pygit2/issues/432>`_
|
||||
|
||||
- New ``Reference.peel(...)`` renders ``Reference.get_object()`` obsolete
|
||||
`#434 <https://github.com/libgit2/pygit2/pull/434>`_
|
||||
|
||||
- New, authenticate using ssh agent
|
||||
`#424 <https://github.com/libgit2/pygit2/pull/424>`_
|
||||
|
||||
- New ``Repository.merge_commits(...)``
|
||||
`#445 <https://github.com/libgit2/pygit2/pull/445>`_
|
||||
|
||||
- Make it easier to run when libgit2 not in a standard location
|
||||
`#441 <https://github.com/libgit2/pygit2/issues/441>`_
|
||||
|
||||
- Documentation: review install chapter
|
||||
|
||||
- Documentation: many corrections
|
||||
`#427 <https://github.com/libgit2/pygit2/pull/427>`_
|
||||
`#429 <https://github.com/libgit2/pygit2/pull/429>`_
|
||||
`#439 <https://github.com/libgit2/pygit2/pull/439>`_
|
||||
`#440 <https://github.com/libgit2/pygit2/pull/440>`_
|
||||
`#442 <https://github.com/libgit2/pygit2/pull/442>`_
|
||||
`#443 <https://github.com/libgit2/pygit2/pull/443>`_
|
||||
`#444 <https://github.com/libgit2/pygit2/pull/444>`_
|
||||
|
||||
|
||||
0.21.3 (2014-09-15)
|
||||
-------------------
|
||||
|
||||
Breaking changes:
|
||||
|
||||
- Now ``Repository.blame(...)`` returns ``Oid`` instead of string
|
||||
`#413 <https://github.com/libgit2/pygit2/pull/413>`_
|
||||
|
||||
- New ``Reference.set_target(...)`` replaces the ``Reference.target`` setter
|
||||
and ``Reference.log_append(...)``
|
||||
`#414 <https://github.com/libgit2/pygit2/pull/414>`_
|
||||
|
||||
- New ``Repository.set_head(...)`` replaces the ``Repository.head`` setter
|
||||
`#414 <https://github.com/libgit2/pygit2/pull/414>`_
|
||||
|
||||
- ``Repository.merge(...)`` now uses the ``SAFE_CREATE`` strategy by default
|
||||
`#417 <https://github.com/libgit2/pygit2/pull/417>`_
|
||||
|
||||
Other changes:
|
||||
|
||||
- New ``Remote.delete()``
|
||||
`#418 <https://github.com/libgit2/pygit2/issues/418>`_
|
||||
`#420 <https://github.com/libgit2/pygit2/pull/420>`_
|
||||
|
||||
- New ``Repository.write_archive(...)``
|
||||
`#421 <https://github.com/libgit2/pygit2/pull/421>`_
|
||||
|
||||
- Now ``Repository.checkout(...)`` accepts branch objects
|
||||
`#408 <https://github.com/libgit2/pygit2/pull/408>`_
|
||||
|
||||
- Fix refcount leak in remotes
|
||||
`#403 <https://github.com/libgit2/pygit2/issues/403>`_
|
||||
`#404 <https://github.com/libgit2/pygit2/pull/404>`_
|
||||
`#419 <https://github.com/libgit2/pygit2/pull/419>`_
|
||||
|
||||
- Various fixes to ``clone_repository(...)``
|
||||
`#399 <https://github.com/libgit2/pygit2/issues/399>`_
|
||||
`#411 <https://github.com/libgit2/pygit2/pull/411>`_
|
||||
`#425 <https://github.com/libgit2/pygit2/issues/425>`_
|
||||
`#426 <https://github.com/libgit2/pygit2/pull/426>`_
|
||||
|
||||
- Fix build error in Python 3
|
||||
`#401 <https://github.com/libgit2/pygit2/pull/401>`_
|
||||
|
||||
- Now ``pip install pygit2`` installs cffi first
|
||||
`#380 <https://github.com/libgit2/pygit2/issues/380>`_
|
||||
`#407 <https://github.com/libgit2/pygit2/pull/407>`_
|
||||
|
||||
- Add support for PyPy3
|
||||
`#422 <https://github.com/libgit2/pygit2/pull/422>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#398 <https://github.com/libgit2/pygit2/pull/398>`_
|
||||
`#409 <https://github.com/libgit2/pygit2/pull/409>`_
|
||||
|
||||
|
||||
0.21.2 (2014-08-09)
|
||||
-------------------
|
||||
|
||||
- Fix regression with Python 2, ``IndexEntry.path`` returns str
|
||||
(bytes in Python 2 and unicode in Python 3)
|
||||
|
||||
- Get back ``IndexEntry.oid`` for backwards compatibility
|
||||
|
||||
- Config, iterate over the keys (instead of the key/value pairs)
|
||||
`#395 <https://github.com/libgit2/pygit2/pull/395>`_
|
||||
|
||||
- ``Diff.find_similar`` supports new threshold arguments
|
||||
`#396 <https://github.com/libgit2/pygit2/pull/396>`_
|
||||
|
||||
- Optimization, do not load the object when expanding an oid prefix
|
||||
`#397 <https://github.com/libgit2/pygit2/pull/397>`_
|
||||
|
||||
|
||||
0.21.1 (2014-07-22)
|
||||
-------------------
|
||||
|
||||
- Install fix
|
||||
`#382 <https://github.com/libgit2/pygit2/pull/382>`_
|
||||
|
||||
- Documentation improved, including
|
||||
`#383 <https://github.com/libgit2/pygit2/pull/383>`_
|
||||
`#385 <https://github.com/libgit2/pygit2/pull/385>`_
|
||||
`#388 <https://github.com/libgit2/pygit2/pull/388>`_
|
||||
|
||||
- Documentation, use the read-the-docs theme
|
||||
`#387 <https://github.com/libgit2/pygit2/pull/387>`_
|
||||
|
||||
- Coding style improvements
|
||||
`#392 <https://github.com/libgit2/pygit2/pull/392>`_
|
||||
|
||||
- New ``Repository.state_cleanup()``
|
||||
`#386 <https://github.com/libgit2/pygit2/pull/386>`_
|
||||
|
||||
- New ``Index.conflicts``
|
||||
`#345 <https://github.com/libgit2/pygit2/issues/345>`_
|
||||
`#389 <https://github.com/libgit2/pygit2/pull/389>`_
|
||||
|
||||
- New checkout option to define the target directory
|
||||
`#390 <https://github.com/libgit2/pygit2/pull/390>`_
|
||||
|
||||
|
||||
Backward incompatible changes:
|
||||
|
||||
- Now the checkout strategy must be a keyword argument.
|
||||
|
||||
Change ``Repository.checkout(refname, strategy)`` to
|
||||
``Repository.checkout(refname, strategy=strategy)``
|
||||
|
||||
Idem for ``checkout_head``, ``checkout_index`` and ``checkout_tree``
|
||||
|
||||
|
||||
0.21.0 (2014-06-27)
|
||||
-------------------
|
||||
|
||||
Highlights:
|
||||
|
||||
- Drop official support for Python 2.6, and add support for Python 3.4
|
||||
`#376 <https://github.com/libgit2/pygit2/pull/376>`_
|
||||
|
||||
- Upgrade to libgit2 v0.21.0
|
||||
`#374 <https://github.com/libgit2/pygit2/pull/374>`_
|
||||
|
||||
- Start using cffi
|
||||
`#360 <https://github.com/libgit2/pygit2/pull/360>`_
|
||||
`#361 <https://github.com/libgit2/pygit2/pull/361>`_
|
||||
|
||||
Backward incompatible changes:
|
||||
|
||||
- Replace ``oid`` by ``id`` through the API to follow libgit2 conventions.
|
||||
- Merge API overhaul following changes in libgit2.
|
||||
- New ``Remote.rename(...)`` replaces ``Remote.name = ...``
|
||||
- Now ``Remote.fetch()`` returns a ``TransferProgress`` object.
|
||||
- Now ``Config.get_multivar(...)`` returns an iterator instead of a list.
|
||||
|
||||
New features:
|
||||
|
||||
- New ``Config.snapshot()`` and ``Repository.config_snapshot()``
|
||||
|
||||
- New ``Config`` methods: ``get_bool(...)``, ``get_int(...)``,
|
||||
``parse_bool(...)`` and ``parse_int(...)``
|
||||
`#357 <https://github.com/libgit2/pygit2/pull/357>`_
|
||||
|
||||
- Blob: implement the memory buffer interface
|
||||
`#362 <https://github.com/libgit2/pygit2/pull/362>`_
|
||||
|
||||
- New ``clone_into(...)`` function
|
||||
`#368 <https://github.com/libgit2/pygit2/pull/368>`_
|
||||
|
||||
- Now ``Index`` can be used alone, without a repository
|
||||
`#372 <https://github.com/libgit2/pygit2/pull/372>`_
|
||||
|
||||
- Add more options to ``init_repository``
|
||||
`#347 <https://github.com/libgit2/pygit2/pull/347>`_
|
||||
|
||||
- Support ``Repository.workdir = ...`` and
|
||||
support setting detached heads ``Repository.head = <Oid>``
|
||||
`#377 <https://github.com/libgit2/pygit2/pull/377>`_
|
||||
|
||||
Other:
|
||||
|
||||
- Fix again build with VS2008
|
||||
`#364 <https://github.com/libgit2/pygit2/pull/364>`_
|
||||
|
||||
- Fix ``Blob.diff(...)`` and ``Blob.diff_to_buffer(...)`` arguments passing
|
||||
`#366 <https://github.com/libgit2/pygit2/pull/366>`_
|
||||
|
||||
- Fail gracefully when compiling against the wrong version of libgit2
|
||||
`#365 <https://github.com/libgit2/pygit2/pull/365>`_
|
||||
|
||||
- Several documentation improvements and updates
|
||||
`#359 <https://github.com/libgit2/pygit2/pull/359>`_
|
||||
`#375 <https://github.com/libgit2/pygit2/pull/375>`_
|
||||
`#378 <https://github.com/libgit2/pygit2/pull/378>`_
|
||||
|
||||
|
||||
|
||||
0.20.3 (2014-04-02)
|
||||
-------------------
|
||||
|
||||
- A number of memory issues fixed
|
||||
`#328 <https://github.com/libgit2/pygit2/pull/328>`_
|
||||
`#348 <https://github.com/libgit2/pygit2/pull/348>`_
|
||||
`#353 <https://github.com/libgit2/pygit2/pull/353>`_
|
||||
`#355 <https://github.com/libgit2/pygit2/pull/355>`_
|
||||
`#356 <https://github.com/libgit2/pygit2/pull/356>`_
|
||||
- Compatibility fixes for
|
||||
PyPy (`#338 <https://github.com/libgit2/pygit2/pull/338>`_),
|
||||
Visual Studio 2008 (`#343 <https://github.com/libgit2/pygit2/pull/343>`_)
|
||||
and Python 3.3 (`#351 <https://github.com/libgit2/pygit2/pull/351>`_)
|
||||
- Make the sort mode parameter in ``Repository.walk(...)`` optional
|
||||
`#337 <https://github.com/libgit2/pygit2/pull/337>`_
|
||||
- New ``Object.peel(...)``
|
||||
`#342 <https://github.com/libgit2/pygit2/pull/342>`_
|
||||
- New ``Index.add_all(...)``
|
||||
`#344 <https://github.com/libgit2/pygit2/pull/344>`_
|
||||
- Introduce support for libgit2 options
|
||||
`#350 <https://github.com/libgit2/pygit2/pull/350>`_
|
||||
- More informative repr for ``Repository`` objects
|
||||
`#352 <https://github.com/libgit2/pygit2/pull/352>`_
|
||||
- Introduce support for credentials
|
||||
`#354 <https://github.com/libgit2/pygit2/pull/354>`_
|
||||
- Several documentation fixes
|
||||
`#302 <https://github.com/libgit2/pygit2/issues/302>`_
|
||||
`#336 <https://github.com/libgit2/pygit2/issues/336>`_
|
||||
- Tests, remove temporary files
|
||||
`#341 <https://github.com/libgit2/pygit2/pull/341>`_
|
||||
|
||||
|
||||
0.20.2 (2014-02-04)
|
||||
-------------------
|
||||
|
||||
- Support PyPy
|
||||
`#209 <https://github.com/libgit2/pygit2/issues/209>`_
|
||||
`#327 <https://github.com/libgit2/pygit2/pull/327>`_
|
||||
`#333 <https://github.com/libgit2/pygit2/pull/333>`_
|
||||
|
||||
Repository:
|
||||
|
||||
- New ``Repository.default_signature``
|
||||
`#310 <https://github.com/libgit2/pygit2/pull/310>`_
|
||||
|
||||
Oid:
|
||||
|
||||
- New ``str(Oid)`` deprecates ``Oid.hex``
|
||||
`#322 <https://github.com/libgit2/pygit2/pull/322>`_
|
||||
|
||||
Object:
|
||||
|
||||
- New ``Object.id`` deprecates ``Object.oid``
|
||||
`#322 <https://github.com/libgit2/pygit2/pull/322>`_
|
||||
|
||||
- New ``TreeEntry.id`` deprecates ``TreeEntry.oid``
|
||||
`#322 <https://github.com/libgit2/pygit2/pull/322>`_
|
||||
|
||||
- New ``Blob.diff(...)`` and ``Blob.diff_to_buffer(...)``
|
||||
`#307 <https://github.com/libgit2/pygit2/pull/307>`_
|
||||
|
||||
- New ``Commit.tree_id`` and ``Commit.parent_ids``
|
||||
`#73 <https://github.com/libgit2/pygit2/issues/73>`_
|
||||
`#311 <https://github.com/libgit2/pygit2/pull/311>`_
|
||||
|
||||
- New rich comparison between tree entries
|
||||
`#305 <https://github.com/libgit2/pygit2/issues/305>`_
|
||||
`#313 <https://github.com/libgit2/pygit2/pull/313>`_
|
||||
|
||||
- Now ``Tree.__contains__(key)`` supports paths
|
||||
`#306 <https://github.com/libgit2/pygit2/issues/306>`_
|
||||
`#316 <https://github.com/libgit2/pygit2/pull/316>`_
|
||||
|
||||
Index:
|
||||
|
||||
- Now possible to create ``IndexEntry(...)``
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Now ``IndexEntry.path``, ``IndexEntry.oid`` and ``IndexEntry.mode`` are
|
||||
writable
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Now ``Index.add(...)`` accepts an ``IndexEntry`` too
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Now ``Index.write_tree(...)`` is able to write to a different repository
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Fix memory leak in ``IndexEntry.path`` setter
|
||||
`#335 <https://github.com/libgit2/pygit2/pull/335>`_
|
||||
|
||||
Config:
|
||||
|
||||
- New ``Config`` iterator replaces ``Config.foreach``
|
||||
`#183 <https://github.com/libgit2/pygit2/issues/183>`_
|
||||
`#312 <https://github.com/libgit2/pygit2/pull/312>`_
|
||||
|
||||
Remote:
|
||||
|
||||
- New type ``Refspec``
|
||||
`#314 <https://github.com/libgit2/pygit2/pull/314>`_
|
||||
|
||||
- New ``Remote.push_url``
|
||||
`#315 <https://github.com/libgit2/pygit2/pull/314>`_
|
||||
|
||||
- New ``Remote.add_push`` and ``Remote.add_fetch``
|
||||
`#255 <https://github.com/libgit2/pygit2/issues/255>`_
|
||||
`#318 <https://github.com/libgit2/pygit2/pull/318>`_
|
||||
|
||||
- New ``Remote.fetch_refspecs`` replaces ``Remote.get_fetch_refspecs()`` and
|
||||
``Remote.set_fetch_refspecs(...)``
|
||||
`#319 <https://github.com/libgit2/pygit2/pull/319>`_
|
||||
|
||||
- New ``Remote.push_refspecs`` replaces ``Remote.get_push_refspecs()`` and
|
||||
``Remote.set_push_refspecs(...)``
|
||||
`#319 <https://github.com/libgit2/pygit2/pull/319>`_
|
||||
|
||||
- New ``Remote.progress``, ``Remote.transfer_progress`` and
|
||||
``Remote.update_tips``
|
||||
`#274 <https://github.com/libgit2/pygit2/issues/274>`_
|
||||
`#324 <https://github.com/libgit2/pygit2/pull/324>`_
|
||||
|
||||
- New type ``TransferProgress``
|
||||
`#274 <https://github.com/libgit2/pygit2/issues/274>`_
|
||||
`#324 <https://github.com/libgit2/pygit2/pull/324>`_
|
||||
|
||||
- Fix refcount leak in ``Repository.remotes``
|
||||
`#321 <https://github.com/libgit2/pygit2/issues/321>`_
|
||||
`#332 <https://github.com/libgit2/pygit2/pull/332>`_
|
||||
|
||||
Other: `#331 <https://github.com/libgit2/pygit2/pull/331>`_
|
||||
|
||||
|
||||
0.20.1 (2013-12-24)
|
||||
-------------------
|
||||
|
||||
- New remote ref-specs API:
|
||||
`#290 <https://github.com/libgit2/pygit2/pull/290>`_
|
||||
|
||||
- New ``Repository.reset(...)``:
|
||||
`#292 <https://github.com/libgit2/pygit2/pull/292>`_,
|
||||
`#294 <https://github.com/libgit2/pygit2/pull/294>`_
|
||||
|
||||
- Export ``GIT_DIFF_MINIMAL``:
|
||||
`#293 <https://github.com/libgit2/pygit2/pull/293>`_
|
||||
|
||||
- New ``Repository.merge(...)``:
|
||||
`#295 <https://github.com/libgit2/pygit2/pull/295>`_
|
||||
|
||||
- Fix ``Repository.blame`` argument handling:
|
||||
`#297 <https://github.com/libgit2/pygit2/pull/297>`_
|
||||
|
||||
- Fix build error on Windows:
|
||||
`#298 <https://github.com/libgit2/pygit2/pull/298>`_
|
||||
|
||||
- Fix typo in the README file, Blog → Blob:
|
||||
`#301 <https://github.com/libgit2/pygit2/pull/301>`_
|
||||
|
||||
- Now ``Diff.patch`` returns ``None`` if no patch:
|
||||
`#232 <https://github.com/libgit2/pygit2/pull/232>`_,
|
||||
`#303 <https://github.com/libgit2/pygit2/pull/303>`_
|
||||
|
||||
- New ``Walker.simplify_first_parent()``:
|
||||
`#304 <https://github.com/libgit2/pygit2/pull/304>`_
|
||||
|
||||
0.20.0 (2013-11-24)
|
||||
-------------------
|
||||
|
||||
- Upgrade to libgit2 v0.20.0:
|
||||
`#288 <https://github.com/libgit2/pygit2/pull/288>`_
|
||||
|
||||
- New ``Repository.head_is_unborn`` replaces ``Repository.head_is_orphaned``
|
||||
|
||||
- Changed ``pygit2.clone_repository(...)``. Drop ``push_url``, ``fetch_spec``
|
||||
and ``push_spec`` parameters. Add ``ignore_cert_errors``.
|
||||
|
||||
- New ``Patch.additions`` and ``Patch.deletions``:
|
||||
`#275 <https://github.com/libgit2/pygit2/pull/275>`_
|
||||
|
||||
- New ``Patch.is_binary``:
|
||||
`#276 <https://github.com/libgit2/pygit2/pull/276>`_
|
||||
|
||||
- New ``Reference.log_append(...)``:
|
||||
`#277 <https://github.com/libgit2/pygit2/pull/277>`_
|
||||
|
||||
- New ``Blob.is_binary``:
|
||||
`#278 <https://github.com/libgit2/pygit2/pull/278>`_
|
||||
|
||||
- New ``len(Diff)`` shows the number of patches:
|
||||
`#281 <https://github.com/libgit2/pygit2/pull/281>`_
|
||||
|
||||
- Rewrite ``Repository.status()``:
|
||||
`#283 <https://github.com/libgit2/pygit2/pull/283>`_
|
||||
|
||||
- New ``Reference.shorthand``:
|
||||
`#284 <https://github.com/libgit2/pygit2/pull/284>`_
|
||||
|
||||
- New ``Repository.blame(...)``:
|
||||
`#285 <https://github.com/libgit2/pygit2/pull/285>`_
|
||||
|
||||
- Now ``Repository.listall_references()`` and
|
||||
``Repository.listall_branches()`` return a list, not a tuple:
|
||||
`#289 <https://github.com/libgit2/pygit2/pull/289>`_
|
711
README.rst
711
README.rst
@ -5,16 +5,19 @@ pygit2 - libgit2 bindings in Python
|
||||
.. image:: https://travis-ci.org/libgit2/pygit2.svg?branch=master
|
||||
:target: http://travis-ci.org/libgit2/pygit2
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/edmwc0dctk5nacx0/branch/master?svg=true
|
||||
:target: https://ci.appveyor.com/project/jdavid/pygit2/branch/master
|
||||
|
||||
Pygit2 is a set of Python bindings to the libgit2 shared library, libgit2
|
||||
implements the core of Git. Pygit2 works with Python 2.7, 3.2, 3.3, 3.4 and
|
||||
pypy.
|
||||
implements Git plumbing. Pygit2 works with Python 2.7, 3.3, 3.4, 3.5, 3.6
|
||||
and PyPy 2.6
|
||||
|
||||
Links:
|
||||
|
||||
- http://github.com/libgit2/pygit2 -- Source code and issue tracker
|
||||
- https://github.com/libgit2/pygit2 -- Source code and issue tracker
|
||||
- http://www.pygit2.org/ -- Documentation
|
||||
- http://pypi.python.org/pypi/pygit2 -- Download
|
||||
|
||||
- https://pypi.python.org/pypi/pygit2 -- Download
|
||||
- https://github.com/libgit2/pygit2/blob/master/CHANGELOG.rst -- Changelog
|
||||
|
||||
How to install
|
||||
==============
|
||||
@ -22,680 +25,50 @@ How to install
|
||||
- Check http://www.pygit2.org/install.html
|
||||
|
||||
|
||||
Changelog
|
||||
==============
|
||||
|
||||
0.23.0 (2015-08-14)
|
||||
-------------------------
|
||||
|
||||
- Update to libgit2 v0.23
|
||||
`#540 <https://github.com/libgit2/pygit2/pull/540>`_
|
||||
|
||||
- Now ``Repository.merge_base(...)`` returns ``None`` if no merge base is found
|
||||
`#550 <https://github.com/libgit2/pygit2/pull/550>`_
|
||||
|
||||
- Documentation updates
|
||||
`#547 <https://github.com/libgit2/pygit2/pull/547>`_
|
||||
|
||||
API changes:
|
||||
|
||||
- How to set identity (aka signature) in a reflog has changed::
|
||||
|
||||
# Before
|
||||
signature = Signature('foo', 'bar')
|
||||
...
|
||||
reference.set_target(target, signature=signature, message=message)
|
||||
repo.set_head(target, signature=signature)
|
||||
remote.fetch(signature=signature)
|
||||
remote.push(signature=signature)
|
||||
|
||||
# Now
|
||||
repo.set_ident('foo', 'bar')
|
||||
...
|
||||
reference.set_target(target, message=message)
|
||||
repo.set_head(target)
|
||||
remote.push()
|
||||
|
||||
# The current identity can be get with
|
||||
repo.ident
|
||||
|
||||
- Some remote setters have been replaced by methods::
|
||||
|
||||
# Before # Now
|
||||
Remote.url = url Repository.remotes.set_url(name, url)
|
||||
Remote.push_url = url Repository.remotes.set_push_url(name, url)
|
||||
|
||||
Remote.add_fetch(refspec) Repository.remotes.add_fetch(name, refspec)
|
||||
Remote.add_push(refspec) Repository.remotes.add_push(name, refspec)
|
||||
|
||||
Remote.fetch_refspecs = [...] removed, use the config API instead
|
||||
Remote.push_refspecs = [...] removed, use the config API instead
|
||||
|
||||
|
||||
0.22.1 (2015-07-12)
|
||||
-------------------------
|
||||
|
||||
Diff interface refactoring
|
||||
`#346 <https://github.com/libgit2/pygit2/pull/346>`_
|
||||
(in progress):
|
||||
|
||||
- New ``iter(pygit2.Blame)``
|
||||
|
||||
- New ``pygit2.DiffDelta``, ``pygit2.DiffFile`` and ``pygit.DiffLine``
|
||||
|
||||
- API changes, translation table::
|
||||
|
||||
Hunk => DiffHunk
|
||||
Patch.old_file_path => Patch.delta.old_file.path
|
||||
Patch.new_file_path => Patch.delta.new_file.path
|
||||
Patch.old_id => Patch.delta.old_file.id
|
||||
Patch.new_id => Patch.delta.new_file.id
|
||||
Patch.status => Patch.delta.status
|
||||
Patch.similarity => Patch.delta.similarity
|
||||
Patch.is_binary => Patch.delta.is_binary
|
||||
Patch.additions => Patch.line_stats[1]
|
||||
Patch.deletions => Patch.line_stats[2]
|
||||
|
||||
- ``DiffHunk.lines`` is now a list of ``DiffLine`` objects, not tuples
|
||||
|
||||
New features:
|
||||
|
||||
- New ``Repository.expand_id(...)`` and ``Repository.ahead_behind(...)``
|
||||
`#448 <https://github.com/libgit2/pygit2/pull/448>`_
|
||||
|
||||
- New ``prefix`` parameter in ``Repository.write_archive``
|
||||
`#481 <https://github.com/libgit2/pygit2/pull/481>`_
|
||||
|
||||
- New ``Repository.merge_trees(...)``
|
||||
`#489 <https://github.com/libgit2/pygit2/pull/489>`_
|
||||
|
||||
- New ``Repository.cherrypick(...)``
|
||||
`#436 <https://github.com/libgit2/pygit2/issues/436>`_
|
||||
`#492 <https://github.com/libgit2/pygit2/pull/492>`_
|
||||
|
||||
- New support for submodules
|
||||
`#499 <https://github.com/libgit2/pygit2/pull/499>`_
|
||||
`#514 <https://github.com/libgit2/pygit2/pull/514>`_
|
||||
|
||||
- New ``Repository.merge_file_from_index(...)``
|
||||
`#503 <https://github.com/libgit2/pygit2/pull/503>`_
|
||||
|
||||
- Now ``Repository.diff`` supports diffing two blobs
|
||||
`#508 <https://github.com/libgit2/pygit2/pull/508>`_
|
||||
|
||||
- New optional ``fetch`` parameter in ``Remote.create``
|
||||
`#526 <https://github.com/libgit2/pygit2/pull/526>`_
|
||||
|
||||
- New ``pygit2.DiffStats``
|
||||
`#406 <https://github.com/libgit2/pygit2/issues/406>`_
|
||||
`#525 <https://github.com/libgit2/pygit2/pull/525>`_
|
||||
|
||||
- New ``Repository.get_attr(...)``
|
||||
`#528 <https://github.com/libgit2/pygit2/pull/528>`_
|
||||
|
||||
- New ``level`` optional parameter in ``Index.remove``
|
||||
`#533 <https://github.com/libgit2/pygit2/pull/533>`_
|
||||
|
||||
- New ``repr(TreeEntry)``
|
||||
`#543 <https://github.com/libgit2/pygit2/pull/543>`_
|
||||
|
||||
Build and install improvements:
|
||||
|
||||
- Make pygit work in a frozen environment
|
||||
`#453 <https://github.com/libgit2/pygit2/pull/453>`_
|
||||
|
||||
- Make pygit2 work with pyinstaller
|
||||
`#510 <https://github.com/libgit2/pygit2/pull/510>`_
|
||||
|
||||
Bugs fixed:
|
||||
|
||||
- Fix memory issues
|
||||
`#477 <https://github.com/libgit2/pygit2/issues/477>`_
|
||||
`#487 <https://github.com/libgit2/pygit2/pull/487>`_
|
||||
`#520 <https://github.com/libgit2/pygit2/pull/520>`_
|
||||
|
||||
- Fix TreeEntry equality testing
|
||||
`#458 <https://github.com/libgit2/pygit2/issues/458>`_
|
||||
`#488 <https://github.com/libgit2/pygit2/pull/488>`_
|
||||
|
||||
- ``Repository.write_archive`` fix handling of symlinks
|
||||
`#480 <https://github.com/libgit2/pygit2/pull/480>`_
|
||||
|
||||
- Fix type check in ``Diff[...]``
|
||||
`#495 <https://github.com/libgit2/pygit2/issues/495>`_
|
||||
|
||||
- Fix error when merging files with unicode content
|
||||
`#505 <https://github.com/libgit2/pygit2/pull/505>`_
|
||||
|
||||
Other:
|
||||
|
||||
- Documentation improvements and fixes
|
||||
`#448 <https://github.com/libgit2/pygit2/pull/448>`_
|
||||
`#491 <https://github.com/libgit2/pygit2/pull/491>`_
|
||||
`#497 <https://github.com/libgit2/pygit2/pull/497>`_
|
||||
`#507 <https://github.com/libgit2/pygit2/pull/507>`_
|
||||
`#517 <https://github.com/libgit2/pygit2/pull/517>`_
|
||||
`#518 <https://github.com/libgit2/pygit2/pull/518>`_
|
||||
`#519 <https://github.com/libgit2/pygit2/pull/519>`_
|
||||
`#521 <https://github.com/libgit2/pygit2/pull/521>`_
|
||||
`#523 <https://github.com/libgit2/pygit2/pull/523>`_
|
||||
`#527 <https://github.com/libgit2/pygit2/pull/527>`_
|
||||
`#536 <https://github.com/libgit2/pygit2/pull/536>`_
|
||||
|
||||
- Expose the ``pygit2.GIT_REPOSITORY_INIT_*`` constants
|
||||
`#483 <https://github.com/libgit2/pygit2/issues/483>`_
|
||||
|
||||
|
||||
0.22.0 (2015-01-16)
|
||||
-------------------
|
||||
|
||||
New:
|
||||
|
||||
- Update to libgit2 v0.22
|
||||
`#459 <https://github.com/libgit2/pygit2/pull/459>`_
|
||||
|
||||
- Add support for libgit2 feature detection
|
||||
(new ``pygit2.features`` and ``pygit2.GIT_FEATURE_*``)
|
||||
`#475 <https://github.com/libgit2/pygit2/pull/475>`_
|
||||
|
||||
- New ``Repository.remotes`` (``RemoteCollection``)
|
||||
`#447 <https://github.com/libgit2/pygit2/pull/447>`_
|
||||
|
||||
API Changes:
|
||||
|
||||
- Prototype of ``clone_repository`` changed, check documentation
|
||||
|
||||
- Removed ``clone_into``, use ``clone_repository`` with callbacks instead
|
||||
|
||||
- Use ``Repository.remotes.rename(name, new_name)`` instead of
|
||||
``Remote.rename(new_name)``
|
||||
|
||||
- Use ``Repository.remotes.delete(name)`` instead of ``Remote.delete()``
|
||||
|
||||
- Now ``Remote.push(...)`` takes a list of refspecs instead of just one
|
||||
|
||||
- Change ``Patch.old_id``, ``Patch.new_id``, ``Note.annotated_id``,
|
||||
``RefLogEntry.oid_old`` and ``RefLogEntry.oid_new`` to be ``Oid`` objects
|
||||
instead of strings
|
||||
`#449 <https://github.com/libgit2/pygit2/pull/449>`_
|
||||
|
||||
Other:
|
||||
|
||||
- Fix ``init_repository`` when passing optional parameters ``workdir_path``,
|
||||
``description``, ``template_path``, ``initial_head`` or ``origin_url``
|
||||
`#466 <https://github.com/libgit2/pygit2/issues/466>`_
|
||||
`#471 <https://github.com/libgit2/pygit2/pull/471>`_
|
||||
|
||||
- Fix use-after-free when patch outlives diff
|
||||
`#457 <https://github.com/libgit2/pygit2/issues/457>`_
|
||||
`#461 <https://github.com/libgit2/pygit2/pull/461>`_
|
||||
`#474 <https://github.com/libgit2/pygit2/pull/474>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#456 <https://github.com/libgit2/pygit2/issues/456>`_
|
||||
`#462 <https://github.com/libgit2/pygit2/pull/462>`_
|
||||
`#465 <https://github.com/libgit2/pygit2/pull/465>`_
|
||||
`#472 <https://github.com/libgit2/pygit2/pull/472>`_
|
||||
`#473 <https://github.com/libgit2/pygit2/pull/473>`_
|
||||
|
||||
- Make the GPL exception explicit in setup.py
|
||||
`#450 <https://github.com/libgit2/pygit2/pull/450>`_
|
||||
|
||||
|
||||
0.21.4 (2014-11-04)
|
||||
-------------------
|
||||
|
||||
- Fix credentials callback not set when pushing
|
||||
`#431 <https://github.com/libgit2/pygit2/pull/431>`_
|
||||
`#435 <https://github.com/libgit2/pygit2/issues/435>`_
|
||||
`#437 <https://github.com/libgit2/pygit2/issues/437>`_
|
||||
`#438 <https://github.com/libgit2/pygit2/pull/438>`_
|
||||
|
||||
- Fix ``Repository.diff(...)`` when treeish is "empty"
|
||||
`#432 <https://github.com/libgit2/pygit2/issues/432>`_
|
||||
|
||||
- New ``Reference.peel(...)`` renders ``Reference.get_object()`` obsolete
|
||||
`#434 <https://github.com/libgit2/pygit2/pull/434>`_
|
||||
|
||||
- New, authenticate using ssh agent
|
||||
`#424 <https://github.com/libgit2/pygit2/pull/424>`_
|
||||
|
||||
- New ``Repository.merge_commits(...)``
|
||||
`#445 <https://github.com/libgit2/pygit2/pull/445>`_
|
||||
|
||||
- Make it easier to run when libgit2 not in a standard location
|
||||
`#441 <https://github.com/libgit2/pygit2/issues/441>`_
|
||||
|
||||
- Documentation: review install chapter
|
||||
|
||||
- Documentation: many corrections
|
||||
`#427 <https://github.com/libgit2/pygit2/pull/427>`_
|
||||
`#429 <https://github.com/libgit2/pygit2/pull/429>`_
|
||||
`#439 <https://github.com/libgit2/pygit2/pull/439>`_
|
||||
`#440 <https://github.com/libgit2/pygit2/pull/440>`_
|
||||
`#442 <https://github.com/libgit2/pygit2/pull/442>`_
|
||||
`#443 <https://github.com/libgit2/pygit2/pull/443>`_
|
||||
`#444 <https://github.com/libgit2/pygit2/pull/444>`_
|
||||
|
||||
|
||||
0.21.3 (2014-09-15)
|
||||
-------------------
|
||||
|
||||
Breaking changes:
|
||||
|
||||
- Now ``Repository.blame(...)`` returns ``Oid`` instead of string
|
||||
`#413 <https://github.com/libgit2/pygit2/pull/413>`_
|
||||
|
||||
- New ``Reference.set_target(...)`` replaces the ``Reference.target`` setter
|
||||
and ``Reference.log_append(...)``
|
||||
`#414 <https://github.com/libgit2/pygit2/pull/414>`_
|
||||
|
||||
- New ``Repository.set_head(...)`` replaces the ``Repository.head`` setter
|
||||
`#414 <https://github.com/libgit2/pygit2/pull/414>`_
|
||||
|
||||
- ``Repository.merge(...)`` now uses the ``SAFE_CREATE`` strategy by default
|
||||
`#417 <https://github.com/libgit2/pygit2/pull/417>`_
|
||||
|
||||
Other changes:
|
||||
|
||||
- New ``Remote.delete()``
|
||||
`#418 <https://github.com/libgit2/pygit2/issues/418>`_
|
||||
`#420 <https://github.com/libgit2/pygit2/pull/420>`_
|
||||
|
||||
- New ``Repository.write_archive(...)``
|
||||
`#421 <https://github.com/libgit2/pygit2/pull/421>`_
|
||||
|
||||
- Now ``Repository.checkout(...)`` accepts branch objects
|
||||
`#408 <https://github.com/libgit2/pygit2/pull/408>`_
|
||||
|
||||
- Fix refcount leak in remotes
|
||||
`#403 <https://github.com/libgit2/pygit2/issues/403>`_
|
||||
`#404 <https://github.com/libgit2/pygit2/pull/404>`_
|
||||
`#419 <https://github.com/libgit2/pygit2/pull/419>`_
|
||||
|
||||
- Various fixes to ``clone_repository(...)``
|
||||
`#399 <https://github.com/libgit2/pygit2/issues/399>`_
|
||||
`#411 <https://github.com/libgit2/pygit2/pull/411>`_
|
||||
`#425 <https://github.com/libgit2/pygit2/issues/425>`_
|
||||
`#426 <https://github.com/libgit2/pygit2/pull/426>`_
|
||||
|
||||
- Fix build error in Python 3
|
||||
`#401 <https://github.com/libgit2/pygit2/pull/401>`_
|
||||
|
||||
- Now ``pip install pygit2`` installs cffi first
|
||||
`#380 <https://github.com/libgit2/pygit2/issues/380>`_
|
||||
`#407 <https://github.com/libgit2/pygit2/pull/407>`_
|
||||
|
||||
- Add support for pypy3
|
||||
`#422 <https://github.com/libgit2/pygit2/pull/422>`_
|
||||
|
||||
- Documentation improvements
|
||||
`#398 <https://github.com/libgit2/pygit2/pull/398>`_
|
||||
`#409 <https://github.com/libgit2/pygit2/pull/409>`_
|
||||
|
||||
|
||||
0.21.2 (2014-08-09)
|
||||
-------------------
|
||||
|
||||
- Fix regression with Python 2, ``IndexEntry.path`` returns str
|
||||
(bytes in Python 2 and unicode in Python 3)
|
||||
|
||||
- Get back ``IndexEntry.oid`` for backwards compatibility
|
||||
|
||||
- Config, iterate over the keys (instead of the key/value pairs)
|
||||
`#395 <https://github.com/libgit2/pygit2/pull/395>`_
|
||||
|
||||
- ``Diff.find_similar`` supports new threshold arguments
|
||||
`#396 <https://github.com/libgit2/pygit2/pull/396>`_
|
||||
|
||||
- Optimization, do not load the object when expanding an oid prefix
|
||||
`#397 <https://github.com/libgit2/pygit2/pull/397>`_
|
||||
|
||||
|
||||
0.21.1 (2014-07-22)
|
||||
-------------------
|
||||
|
||||
- Install fix
|
||||
`#382 <https://github.com/libgit2/pygit2/pull/382>`_
|
||||
|
||||
- Documentation improved, including
|
||||
`#383 <https://github.com/libgit2/pygit2/pull/383>`_
|
||||
`#385 <https://github.com/libgit2/pygit2/pull/385>`_
|
||||
`#388 <https://github.com/libgit2/pygit2/pull/388>`_
|
||||
|
||||
- Documentation, use the read-the-docs theme
|
||||
`#387 <https://github.com/libgit2/pygit2/pull/387>`_
|
||||
|
||||
- Coding style improvements
|
||||
`#392 <https://github.com/libgit2/pygit2/pull/392>`_
|
||||
|
||||
- New ``Repository.state_cleanup()``
|
||||
`#386 <https://github.com/libgit2/pygit2/pull/386>`_
|
||||
|
||||
- New ``Index.conflicts``
|
||||
`#345 <https://github.com/libgit2/pygit2/issues/345>`_
|
||||
`#389 <https://github.com/libgit2/pygit2/pull/389>`_
|
||||
|
||||
- New checkout option to define the target directory
|
||||
`#390 <https://github.com/libgit2/pygit2/pull/390>`_
|
||||
|
||||
|
||||
Backward incompatible changes:
|
||||
|
||||
- Now the checkout strategy must be a keyword argument.
|
||||
|
||||
Change ``Repository.checkout(refname, strategy)`` to
|
||||
``Repository.checkout(refname, strategy=strategy)``
|
||||
|
||||
Idem for ``checkout_head``, ``checkout_index`` and ``checkout_tree``
|
||||
|
||||
|
||||
0.21.0 (2014-06-27)
|
||||
-------------------
|
||||
|
||||
Highlights:
|
||||
|
||||
- Drop official support for Python 2.6, and add support for Python 3.4
|
||||
`#376 <https://github.com/libgit2/pygit2/pull/376>`_
|
||||
|
||||
- Upgrade to libgit2 v0.21.0
|
||||
`#374 <https://github.com/libgit2/pygit2/pull/374>`_
|
||||
|
||||
- Start using cffi
|
||||
`#360 <https://github.com/libgit2/pygit2/pull/360>`_
|
||||
`#361 <https://github.com/libgit2/pygit2/pull/361>`_
|
||||
|
||||
Backward incompatible changes:
|
||||
|
||||
- Replace ``oid`` by ``id`` through the API to follow libgit2 conventions.
|
||||
- Merge API overhaul following changes in libgit2.
|
||||
- New ``Remote.rename(...)`` replaces ``Remote.name = ...``
|
||||
- Now ``Remote.fetch()`` returns a ``TransferProgress`` object.
|
||||
- Now ``Config.get_multivar(...)`` returns an iterator instead of a list.
|
||||
|
||||
New features:
|
||||
|
||||
- New ``Config.snapshot()`` and ``Repository.config_snapshot()``
|
||||
|
||||
- New ``Config`` methods: ``get_bool(...)``, ``get_int(...)``,
|
||||
``parse_bool(...)`` and ``parse_int(...)``
|
||||
`#357 <https://github.com/libgit2/pygit2/pull/357>`_
|
||||
|
||||
- Blob: implement the memory buffer interface
|
||||
`#362 <https://github.com/libgit2/pygit2/pull/362>`_
|
||||
|
||||
- New ``clone_into(...)`` function
|
||||
`#368 <https://github.com/libgit2/pygit2/pull/368>`_
|
||||
|
||||
- Now ``Index`` can be used alone, without a repository
|
||||
`#372 <https://github.com/libgit2/pygit2/pull/372>`_
|
||||
|
||||
- Add more options to ``init_repository``
|
||||
`#347 <https://github.com/libgit2/pygit2/pull/347>`_
|
||||
|
||||
- Support ``Repository.workdir = ...`` and
|
||||
support setting detached heads ``Repository.head = <Oid>``
|
||||
`#377 <https://github.com/libgit2/pygit2/pull/377>`_
|
||||
|
||||
Other:
|
||||
|
||||
- Fix again build with VS2008
|
||||
`#364 <https://github.com/libgit2/pygit2/pull/364>`_
|
||||
|
||||
- Fix ``Blob.diff(...)`` and ``Blob.diff_to_buffer(...)`` arguments passing
|
||||
`#366 <https://github.com/libgit2/pygit2/pull/366>`_
|
||||
|
||||
- Fail gracefully when compiling against the wrong version of libgit2
|
||||
`#365 <https://github.com/libgit2/pygit2/pull/365>`_
|
||||
|
||||
- Several documentation improvements and updates
|
||||
`#359 <https://github.com/libgit2/pygit2/pull/359>`_
|
||||
`#375 <https://github.com/libgit2/pygit2/pull/375>`_
|
||||
`#378 <https://github.com/libgit2/pygit2/pull/378>`_
|
||||
|
||||
|
||||
|
||||
0.20.3 (2014-04-02)
|
||||
-------------------
|
||||
|
||||
- A number of memory issues fixed
|
||||
`#328 <https://github.com/libgit2/pygit2/pull/328>`_
|
||||
`#348 <https://github.com/libgit2/pygit2/pull/348>`_
|
||||
`#353 <https://github.com/libgit2/pygit2/pull/353>`_
|
||||
`#355 <https://github.com/libgit2/pygit2/pull/355>`_
|
||||
`#356 <https://github.com/libgit2/pygit2/pull/356>`_
|
||||
- Compatibility fixes for
|
||||
PyPy (`#338 <https://github.com/libgit2/pygit2/pull/338>`_),
|
||||
Visual Studio 2008 (`#343 <https://github.com/libgit2/pygit2/pull/343>`_)
|
||||
and Python 3.3 (`#351 <https://github.com/libgit2/pygit2/pull/351>`_)
|
||||
- Make the sort mode parameter in ``Repository.walk(...)`` optional
|
||||
`#337 <https://github.com/libgit2/pygit2/pull/337>`_
|
||||
- New ``Object.peel(...)``
|
||||
`#342 <https://github.com/libgit2/pygit2/pull/342>`_
|
||||
- New ``Index.add_all(...)``
|
||||
`#344 <https://github.com/libgit2/pygit2/pull/344>`_
|
||||
- Introduce support for libgit2 options
|
||||
`#350 <https://github.com/libgit2/pygit2/pull/350>`_
|
||||
- More informative repr for ``Repository`` objects
|
||||
`#352 <https://github.com/libgit2/pygit2/pull/352>`_
|
||||
- Introduce support for credentials
|
||||
`#354 <https://github.com/libgit2/pygit2/pull/354>`_
|
||||
- Several documentation fixes
|
||||
`#302 <https://github.com/libgit2/pygit2/issues/302>`_
|
||||
`#336 <https://github.com/libgit2/pygit2/issues/336>`_
|
||||
- Tests, remove temporary files
|
||||
`#341 <https://github.com/libgit2/pygit2/pull/341>`_
|
||||
|
||||
|
||||
0.20.2 (2014-02-04)
|
||||
-------------------
|
||||
|
||||
- Support pypy
|
||||
`#209 <https://github.com/libgit2/pygit2/issues/209>`_
|
||||
`#327 <https://github.com/libgit2/pygit2/pull/327>`_
|
||||
`#333 <https://github.com/libgit2/pygit2/pull/333>`_
|
||||
|
||||
Repository:
|
||||
|
||||
- New ``Repository.default_signature``
|
||||
`#310 <https://github.com/libgit2/pygit2/pull/310>`_
|
||||
|
||||
Oid:
|
||||
|
||||
- New ``str(Oid)`` deprecates ``Oid.hex``
|
||||
`#322 <https://github.com/libgit2/pygit2/pull/322>`_
|
||||
|
||||
Object:
|
||||
|
||||
- New ``Object.id`` deprecates ``Object.oid``
|
||||
`#322 <https://github.com/libgit2/pygit2/pull/322>`_
|
||||
|
||||
- New ``TreeEntry.id`` deprecates ``TreeEntry.oid``
|
||||
`#322 <https://github.com/libgit2/pygit2/pull/322>`_
|
||||
|
||||
- New ``Blob.diff(...)`` and ``Blob.diff_to_buffer(...)``
|
||||
`#307 <https://github.com/libgit2/pygit2/pull/307>`_
|
||||
|
||||
- New ``Commit.tree_id`` and ``Commit.parent_ids``
|
||||
`#73 <https://github.com/libgit2/pygit2/issues/73>`_
|
||||
`#311 <https://github.com/libgit2/pygit2/pull/311>`_
|
||||
|
||||
- New rich comparison between tree entries
|
||||
`#305 <https://github.com/libgit2/pygit2/issues/305>`_
|
||||
`#313 <https://github.com/libgit2/pygit2/pull/313>`_
|
||||
|
||||
- Now ``Tree.__contains__(key)`` supports paths
|
||||
`#306 <https://github.com/libgit2/pygit2/issues/306>`_
|
||||
`#316 <https://github.com/libgit2/pygit2/pull/316>`_
|
||||
|
||||
Index:
|
||||
|
||||
- Now possible to create ``IndexEntry(...)``
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Now ``IndexEntry.path``, ``IndexEntry.oid`` and ``IndexEntry.mode`` are
|
||||
writable
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Now ``Index.add(...)`` accepts an ``IndexEntry`` too
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Now ``Index.write_tree(...)`` is able to write to a different repository
|
||||
`#325 <https://github.com/libgit2/pygit2/pull/325>`_
|
||||
|
||||
- Fix memory leak in ``IndexEntry.path`` setter
|
||||
`#335 <https://github.com/libgit2/pygit2/pull/335>`_
|
||||
|
||||
Config:
|
||||
|
||||
- New ``Config`` iterator replaces ``Config.foreach``
|
||||
`#183 <https://github.com/libgit2/pygit2/issues/183>`_
|
||||
`#312 <https://github.com/libgit2/pygit2/pull/312>`_
|
||||
|
||||
Remote:
|
||||
|
||||
- New type ``Refspec``
|
||||
`#314 <https://github.com/libgit2/pygit2/pull/314>`_
|
||||
|
||||
- New ``Remote.push_url``
|
||||
`#315 <https://github.com/libgit2/pygit2/pull/314>`_
|
||||
|
||||
- New ``Remote.add_push`` and ``Remote.add_fetch``
|
||||
`#255 <https://github.com/libgit2/pygit2/issues/255>`_
|
||||
`#318 <https://github.com/libgit2/pygit2/pull/318>`_
|
||||
|
||||
- New ``Remote.fetch_refspecs`` replaces ``Remote.get_fetch_refspecs()`` and
|
||||
``Remote.set_fetch_refspecs(...)``
|
||||
`#319 <https://github.com/libgit2/pygit2/pull/319>`_
|
||||
|
||||
- New ``Remote.push_refspecs`` replaces ``Remote.get_push_refspecs()`` and
|
||||
``Remote.set_push_refspecs(...)``
|
||||
`#319 <https://github.com/libgit2/pygit2/pull/319>`_
|
||||
|
||||
- New ``Remote.progress``, ``Remote.transfer_progress`` and
|
||||
``Remote.update_tips``
|
||||
`#274 <https://github.com/libgit2/pygit2/issues/274>`_
|
||||
`#324 <https://github.com/libgit2/pygit2/pull/324>`_
|
||||
|
||||
- New type ``TransferProgress``
|
||||
`#274 <https://github.com/libgit2/pygit2/issues/274>`_
|
||||
`#324 <https://github.com/libgit2/pygit2/pull/324>`_
|
||||
|
||||
- Fix refcount leak in ``Repository.remotes``
|
||||
`#321 <https://github.com/libgit2/pygit2/issues/321>`_
|
||||
`#332 <https://github.com/libgit2/pygit2/pull/332>`_
|
||||
|
||||
Other: `#331 <https://github.com/libgit2/pygit2/pull/331>`_
|
||||
|
||||
|
||||
0.20.1 (2013-12-24)
|
||||
-------------------
|
||||
|
||||
- New remote ref-specs API:
|
||||
`#290 <https://github.com/libgit2/pygit2/pull/290>`_
|
||||
|
||||
- New ``Repository.reset(...)``:
|
||||
`#292 <https://github.com/libgit2/pygit2/pull/292>`_,
|
||||
`#294 <https://github.com/libgit2/pygit2/pull/294>`_
|
||||
|
||||
- Export ``GIT_DIFF_MINIMAL``:
|
||||
`#293 <https://github.com/libgit2/pygit2/pull/293>`_
|
||||
|
||||
- New ``Repository.merge(...)``:
|
||||
`#295 <https://github.com/libgit2/pygit2/pull/295>`_
|
||||
|
||||
- Fix ``Repository.blame`` argument handling:
|
||||
`#297 <https://github.com/libgit2/pygit2/pull/297>`_
|
||||
|
||||
- Fix build error on Windows:
|
||||
`#298 <https://github.com/libgit2/pygit2/pull/298>`_
|
||||
|
||||
- Fix typo in the README file, Blog → Blob:
|
||||
`#301 <https://github.com/libgit2/pygit2/pull/301>`_
|
||||
|
||||
- Now ``Diff.patch`` returns ``None`` if no patch:
|
||||
`#232 <https://github.com/libgit2/pygit2/pull/232>`_,
|
||||
`#303 <https://github.com/libgit2/pygit2/pull/303>`_
|
||||
|
||||
- New ``Walker.simplify_first_parent()``:
|
||||
`#304 <https://github.com/libgit2/pygit2/pull/304>`_
|
||||
|
||||
0.20.0 (2013-11-24)
|
||||
-------------------
|
||||
|
||||
- Upgrade to libgit2 v0.20.0:
|
||||
`#288 <https://github.com/libgit2/pygit2/pull/288>`_
|
||||
|
||||
- New ``Repository.head_is_unborn`` replaces ``Repository.head_is_orphaned``
|
||||
|
||||
- Changed ``pygit2.clone_repository(...)``. Drop ``push_url``, ``fetch_spec``
|
||||
and ``push_spec`` parameters. Add ``ignore_cert_errors``.
|
||||
|
||||
- New ``Patch.additions`` and ``Patch.deletions``:
|
||||
`#275 <https://github.com/libgit2/pygit2/pull/275>`_
|
||||
|
||||
- New ``Patch.is_binary``:
|
||||
`#276 <https://github.com/libgit2/pygit2/pull/276>`_
|
||||
|
||||
- New ``Reference.log_append(...)``:
|
||||
`#277 <https://github.com/libgit2/pygit2/pull/277>`_
|
||||
|
||||
- New ``Blob.is_binary``:
|
||||
`#278 <https://github.com/libgit2/pygit2/pull/278>`_
|
||||
|
||||
- New ``len(Diff)`` shows the number of patches:
|
||||
`#281 <https://github.com/libgit2/pygit2/pull/281>`_
|
||||
|
||||
- Rewrite ``Repository.status()``:
|
||||
`#283 <https://github.com/libgit2/pygit2/pull/283>`_
|
||||
|
||||
- New ``Reference.shorthand``:
|
||||
`#284 <https://github.com/libgit2/pygit2/pull/284>`_
|
||||
|
||||
- New ``Repository.blame(...)``:
|
||||
`#285 <https://github.com/libgit2/pygit2/pull/285>`_
|
||||
|
||||
- Now ``Repository.listall_references()`` and
|
||||
``Repository.listall_branches()`` return a list, not a tuple:
|
||||
`#289 <https://github.com/libgit2/pygit2/pull/289>`_
|
||||
|
||||
|
||||
Authors
|
||||
==============
|
||||
|
||||
93 developers have contributed at least 1 commit to pygit2::
|
||||
117 developers have contributed at least 1 commit to pygit2::
|
||||
|
||||
J. David Ibáñez Carlos Martín Nieto Nico von Geyso
|
||||
W. Trevor King Dave Borowitz Daniel Rodríguez Troitiño
|
||||
Richo Healey Christian Boos Julien Miotte
|
||||
Richard Möhn Xu Tao Jose Plana
|
||||
Matthew Duggan Matthew Gamble Martin Lenders
|
||||
Petr Hosek Victor Garcia Xavier Delannoy
|
||||
Yonggang Luo Patrick Steinhardt Valentin Haenel
|
||||
Michael Jones Bernardo Heynemann John Szakmeister
|
||||
Vlad Temian Brodie Rao David Versmisse
|
||||
Rémi Duraffort Sebastian Thiel Alok Singhal
|
||||
Fraser Tweedale Han-Wen Nienhuys Leonardo Rhodes
|
||||
Petr Viktorin Ron Cohen Santiago Perez De Rosso
|
||||
W. Trevor King Dave Borowitz Matthias Bartelmeß
|
||||
Daniel Rodríguez Troitiño Richo Healey Christian Boos
|
||||
Julien Miotte Richard Möhn Xu Tao
|
||||
Jose Plana Matthew Duggan Matthew Gamble
|
||||
Martin Lenders Nick Hynes Petr Hosek
|
||||
Victor Garcia Xavier Delannoy Yonggang Luo
|
||||
Patrick Steinhardt Tamir Bahar Valentin Haenel
|
||||
Michael Jones Bernardo Heynemann Brodie Rao
|
||||
John Szakmeister Vlad Temian Lukas Fleischer
|
||||
Nicolas Dandrimont David Versmisse Rémi Duraffort
|
||||
Santiago Perez De Rosso Sebastian Thiel Thom Wiggers
|
||||
Alok Singhal Anatoly Techtonik Fraser Tweedale
|
||||
Han-Wen Nienhuys Jason Ziglar Leonardo Rhodes
|
||||
Petr Viktorin Robert Hölzl Ron Cohen
|
||||
Thomas Kluyver Alex Chamberlain Alexander Bayandin
|
||||
Amit Bakshi Andrey Devyatkin Arno van Lumig
|
||||
Ben Davis Eric Schrijver Greg Fitzgerald
|
||||
Hervé Cauwelier Huang Huang Ian P. McCullough
|
||||
Ben Davis Dustin Raimondi Eric Schrijver
|
||||
Greg Fitzgerald Guillermo Pérez Hervé Cauwelier
|
||||
Huang Huang Ian P. McCullough Igor Gnatenko
|
||||
Jack O'Connor Jared Flatow Jiunn Haur Lim
|
||||
Jun Omae Kaarel Kitsemets Kevin KIN-FOO
|
||||
Sarath Lakshman Vicent Marti Zoran Zaric
|
||||
Adam Spiers Andrew Chin András Veres-Szentkirályi
|
||||
Ash Berlin Benjamin Kircher Benjamin Pollack
|
||||
Bryan O'Sullivan Colin Watson Daniel Bruce
|
||||
David Fischer David Sanders Devaev Maxim
|
||||
Mark Adams Masud Rahman Michael Sondergaard
|
||||
Ondřej Nový Sarath Lakshman Szucs Krisztian
|
||||
Vicent Marti Zoran Zaric Adam Spiers
|
||||
Andrew Chin András Veres-Szentkirályi Ash Berlin
|
||||
Benjamin Kircher Benjamin Pollack Bryan O'Sullivan
|
||||
Cam Cope Chason Chaffin Chris Rebert
|
||||
Colin Watson Daniel Bruce David Fischer
|
||||
David Sanders David Six Devaev Maxim
|
||||
Eric Davis Erik Meusel Erik van Zijst
|
||||
Ferengee Gustavo Di Pietro Holger Frey
|
||||
Hugh Cole-Baker Jasper Lievisse Josh Bleecher Snyder
|
||||
Justin Clift Kyriakos Oikonomakos Lukas Fleischer
|
||||
Mathieu Bridon Michael Sondergaard Óscar San José
|
||||
Peter Dave Hello Philippe Ombredanne Ridge Kennedy
|
||||
Ross Nicoll Rui Abreu Ferreira Soasme
|
||||
Vladimir Rutsky chengyuhang earl
|
||||
Ferengee Gustavo Di Pietrou Holger Frey
|
||||
Hugh Cole-Baker Jasper Lievisse Adriaanse Josh Bleecher Snyder
|
||||
Justin Clift Kyriakos Oikonomakos Mathieu Bridon
|
||||
Matthaus Woolard Nicolás Sanguinetti Noah Fontes
|
||||
Óscar San José Peter Dave Hello Philippe Ombredanne
|
||||
Ridge Kennedy Ross Nicoll Rui Abreu Ferreira
|
||||
Sheeo Soasme Vladimir Rutsky
|
||||
Yu Jianjian chengyuhang earl
|
||||
|
||||
|
||||
License
|
||||
|
53
appveyor.yml
Normal file
53
appveyor.yml
Normal file
@ -0,0 +1,53 @@
|
||||
version: 1.0.{build}
|
||||
image: Visual Studio 2015
|
||||
configuration: Release
|
||||
environment:
|
||||
matrix:
|
||||
- GENERATOR: 'Visual Studio 10'
|
||||
PYTHON: 'C:\Python27\python.exe'
|
||||
- GENERATOR: 'Visual Studio 10 Win64'
|
||||
PYTHON: 'C:\Python27-x64\python.exe'
|
||||
- GENERATOR: 'Visual Studio 10'
|
||||
PYTHON: 'C:\Python33\python.exe'
|
||||
- GENERATOR: 'Visual Studio 10 Win64'
|
||||
PYTHON: 'C:\Python33-x64\python.exe'
|
||||
- GENERATOR: 'Visual Studio 10'
|
||||
PYTHON: 'C:\Python34\python.exe'
|
||||
- GENERATOR: 'Visual Studio 10 Win64'
|
||||
PYTHON: 'C:\Python34-x64\python.exe'
|
||||
- GENERATOR: 'Visual Studio 14'
|
||||
PYTHON: 'C:\Python35\python.exe'
|
||||
- GENERATOR: 'Visual Studio 14 Win64'
|
||||
PYTHON: 'C:\Python35-x64\python.exe'
|
||||
- GENERATOR: 'Visual Studio 14'
|
||||
PYTHON: 'C:\Python36\python.exe'
|
||||
- GENERATOR: 'Visual Studio 14 Win64'
|
||||
PYTHON: 'C:\Python36-x64\python.exe'
|
||||
|
||||
init:
|
||||
- cmd: '%PYTHON% -m pip install -U nose wheel'
|
||||
build_script:
|
||||
- cmd: |
|
||||
set LIBGIT2=%APPVEYOR_BUILD_FOLDER%\build\libgit2
|
||||
git clone --depth=1 -b maint/v0.26 https://github.com/libgit2/libgit2.git libgit2
|
||||
mkdir build
|
||||
|
||||
cd build
|
||||
cmake -DSTDCALL=OFF -DBUILD_CLAR=OFF -DCMAKE_INSTALL_PREFIX="%LIBGIT2%" ../libgit2 -G "%GENERATOR%"
|
||||
cmake --build . --config Release --target install
|
||||
cd ..
|
||||
|
||||
IF "%GENERATOR%"=="Visual Studio 10 Win64" ( call "C:\Program Files\Microsoft SDKs\Windows\v7.1\Bin\SetEnv.cmd" )
|
||||
|
||||
"%PYTHON%" setup.py bdist_wheel
|
||||
test_script:
|
||||
- ps: |
|
||||
cp build\Release\git2.dll .
|
||||
&$env:PYTHON setup.py nosetests --with-xunit
|
||||
if ($LastExitCode -ne 0) { $host.SetShouldExit($LastExitCode) }
|
||||
# upload results to AppVeyor
|
||||
$wc = New-Object 'System.Net.WebClient'
|
||||
$wc.UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\nosetests.xml))
|
||||
|
||||
artifacts:
|
||||
- path: dist\*.whl
|
8
docs/backends.rst
Normal file
8
docs/backends.rst
Normal file
@ -0,0 +1,8 @@
|
||||
**********************************************************************
|
||||
Custom backends
|
||||
**********************************************************************
|
||||
|
||||
There is some support for custom backends, but undocumented. See
|
||||
`<https://github.com/libgit2/pygit2/pull/690/commits>`_
|
||||
|
||||
Documentation contributions are very welcome.
|
@ -43,16 +43,16 @@ master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'pygit2'
|
||||
copyright = u'2010-2014 The pygit2 contributors'
|
||||
copyright = u'2010-2015 The pygit2 contributors'
|
||||
|
||||
# The version info for the project you're documenting, acts as replacement for
|
||||
# |version| and |release|, also used in various other places throughout the
|
||||
# built documents.
|
||||
#
|
||||
# The short X.Y version.
|
||||
version = '0.23'
|
||||
version = '0.26'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = '0.23.0'
|
||||
release = '0.26.0'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -5,6 +5,9 @@ The development version
|
||||
.. image:: https://travis-ci.org/libgit2/pygit2.svg?branch=master
|
||||
:target: http://travis-ci.org/libgit2/pygit2
|
||||
|
||||
.. image:: https://ci.appveyor.com/api/projects/status/edmwc0dctk5nacx0/branch/master?svg=true
|
||||
:target: https://ci.appveyor.com/project/jdavid/pygit2/branch/master
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ git clone git://github.com/libgit2/pygit2.git
|
||||
|
@ -83,6 +83,9 @@ Attributes:
|
||||
|
||||
.. autoattribute:: pygit2.DiffFile.path
|
||||
.. autoattribute:: pygit2.DiffFile.id
|
||||
.. autoattribute:: pygit2.DiffFile.size
|
||||
.. autoattribute:: pygit2.DiffFile.flags
|
||||
.. autoattribute:: pygit2.DiffFile.mode
|
||||
|
||||
|
||||
The DiffHunk type
|
||||
@ -108,5 +111,5 @@ The DiffLine type
|
||||
.. autoattribute :: pygit2.DiffLine.origin
|
||||
.. autoattribute :: pygit2.DiffLine.content
|
||||
.. autoattribute :: pygit2.DiffLine.old_lineno
|
||||
.. autoattribute :: pygit2.DiffLine.old_lineno
|
||||
.. autoattribute :: pygit2.DiffLine.new_lineno
|
||||
.. autoattribute :: pygit2.DiffLine.num_lines
|
||||
|
@ -18,7 +18,7 @@ library that has been built against. The version number has a
|
||||
.. py:data:: LIBGIT2_VER_MAJOR
|
||||
|
||||
Integer value of the major version number. For example, for the version
|
||||
``0.23.0``::
|
||||
``0.26.0``::
|
||||
|
||||
>>> print LIBGIT2_VER_MAJOR
|
||||
0
|
||||
@ -26,15 +26,15 @@ library that has been built against. The version number has a
|
||||
.. py:data:: LIBGIT2_VER_MINOR
|
||||
|
||||
Integer value of the minor version number. For example, for the version
|
||||
``0.23.0``::
|
||||
``0.26.0``::
|
||||
|
||||
>>> print LIBGIT2_VER_MINOR
|
||||
22
|
||||
26
|
||||
|
||||
.. py:data:: LIBGIT2_VER_REVISION
|
||||
|
||||
Integer value of the revision version number. For example, for the version
|
||||
``0.23.0``::
|
||||
``0.26.0``::
|
||||
|
||||
>>> print LIBGIT2_VER_REVISION
|
||||
0
|
||||
@ -44,7 +44,7 @@ library that has been built against. The version number has a
|
||||
The libgit2 version number as a string::
|
||||
|
||||
>>> print LIBGIT2_VERSION
|
||||
'0.23.0'
|
||||
'0.26.0'
|
||||
|
||||
Errors
|
||||
======
|
||||
|
@ -7,17 +7,18 @@ Welcome to pygit2's documentation!
|
||||
==================================
|
||||
|
||||
Pygit2 is a set of Python bindings to the libgit2 shared library, libgit2
|
||||
implements the core of Git. Pygit2 works with Python 2.7, 3.2, 3.3, 3.4 and
|
||||
pypy.
|
||||
implements the core of Git. Pygit2 works with Python 2.7, 3.3, 3.4, 3.5,
|
||||
3.6 and pypy.
|
||||
|
||||
It is likely to work with Python 2.6 and 3.1, but these versions are not
|
||||
officially supported.
|
||||
|
||||
Pygit2 links:
|
||||
Links:
|
||||
|
||||
- http://github.com/libgit2/pygit2 -- Source code and issue tracker
|
||||
- https://github.com/libgit2/pygit2 -- Source code and issue tracker
|
||||
- http://www.pygit2.org/ -- Documentation
|
||||
- http://pypi.python.org/pypi/pygit2 -- Download
|
||||
- https://pypi.python.org/pypi/pygit2 -- Download
|
||||
- https://github.com/libgit2/pygit2/blob/master/CHANGELOG.rst -- Changelog
|
||||
|
||||
Start:
|
||||
|
||||
@ -49,6 +50,7 @@ Usage guide:
|
||||
blame
|
||||
settings
|
||||
features
|
||||
backends
|
||||
|
||||
|
||||
Indices and tables
|
||||
|
@ -13,11 +13,19 @@ Installation
|
||||
Requirements
|
||||
============
|
||||
|
||||
- Python 2.7, 3.2+ or pypy (including the development headers)
|
||||
- Libgit2 v0.23.x
|
||||
- cffi 0.8.1+
|
||||
- Libssh2, optional, used for SSH network operations.
|
||||
- pkg-config, optional, used for SSH network operations.
|
||||
- Python 2.7, 3.3+ or PyPy 2.6+ (including the development headers)
|
||||
- Libgit2 v0.26.x
|
||||
- cffi 1.0+
|
||||
- six
|
||||
- tox (optional)
|
||||
|
||||
Optional libgit2 dependecies to support ssh and https:
|
||||
|
||||
- https: WinHTTP (Windows), SecureTransport (OS X) or OpenSSL.
|
||||
- ssh: libssh2, pkg-config
|
||||
|
||||
It should work with older versions of cffi and PyPy, but using cffi 1.0+
|
||||
(and PyPy 2.6+) is strongly encouraged.
|
||||
|
||||
.. warning::
|
||||
|
||||
@ -35,11 +43,11 @@ while the last number |lq| *.micro* |rq| auto-increments independently.
|
||||
|
||||
As illustration see this table of compatible releases:
|
||||
|
||||
+-----------+--------+----------------+----------------------------------------+
|
||||
|**libgit2**| 0.23.0 | 0.22.0, 0.22.1 | 0.21.1, 0.21.2 |
|
||||
+-----------+--------+----------------+----------------------------------------+
|
||||
|**pygit2** | 0.23.0 | 0.22.0 | 0.21.0, 0.21.1, 0.21.2, 0.21.3, 0.21.4 |
|
||||
+-----------+--------+----------------+----------------------------------------+
|
||||
+-----------+--------+----------------+------------------------+
|
||||
|**libgit2**| 0.26.0 | 0.25.0, 0.25.1 | 0.24.0, 0.24.1, 0.24.2 |
|
||||
+-----------+--------+----------------+------------------------+
|
||||
|**pygit2** | 0.26.0 | 0.25.0, 0.25.1 | 0.24.0, 0.24.1, 0.24.2 |
|
||||
+-----------+--------+----------------+------------------------+
|
||||
|
||||
.. warning::
|
||||
|
||||
@ -56,9 +64,9 @@ directory, do:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.0.tar.gz
|
||||
$ tar xzf v0.23.0.tar.gz
|
||||
$ cd libgit2-0.23.0/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.26.0.tar.gz
|
||||
$ tar xzf v0.26.0.tar.gz
|
||||
$ cd libgit2-0.26.0/
|
||||
$ cmake .
|
||||
$ make
|
||||
$ sudo make install
|
||||
@ -140,9 +148,9 @@ Install libgit2 (see we define the installation prefix):
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.0.tar.gz
|
||||
$ tar xzf v0.23.0.tar.gz
|
||||
$ cd libgit2-0.23.0/
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.26.0.tar.gz
|
||||
$ tar xzf v0.26.0.tar.gz
|
||||
$ cd libgit2-0.26.0/
|
||||
$ cmake . -DCMAKE_INSTALL_PREFIX=$LIBGIT2
|
||||
$ make
|
||||
$ make install
|
||||
@ -178,32 +186,34 @@ everytime. Verify yourself if curious:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ readelf --dynamic lib/python2.7/site-packages/pygit2-0.23.0-py2.7-linux-x86_64.egg/_pygit2.so | grep PATH
|
||||
$ readelf --dynamic lib/python2.7/site-packages/pygit2-0.26.0-py2.7-linux-x86_64.egg/_pygit2.so | grep PATH
|
||||
0x000000000000001d (RUNPATH) Library runpath: [/tmp/venv/lib]
|
||||
|
||||
|
||||
Installing on Windows
|
||||
===================================
|
||||
|
||||
pygit2 expects to find the libgit2 installed files in the directory specified
|
||||
in the ``LIBGIT2`` environment variable.
|
||||
`pygit2` for Windows is packaged into wheels and can be easily
|
||||
installed with `pip`:
|
||||
|
||||
In addition, make sure that libgit2 is build in "__cdecl" mode.
|
||||
The following recipe shows you how to do it, assuming you're working
|
||||
from a bash shell:
|
||||
pip install pygit2
|
||||
|
||||
For development it is also possible to build `pygit2` with `libgit2`
|
||||
from sources. `libgit2` location is specified by the ``LIBGIT2``
|
||||
environment variable. `libgit2` should be built in "__cdecl" mode.
|
||||
The following recipe shows you how to do it from a bash shell:
|
||||
|
||||
.. code-block:: sh
|
||||
|
||||
$ export LIBGIT2=C:/Dev/libgit2
|
||||
$ wget https://github.com/libgit2/libgit2/archive/v0.23.0.tar.gz
|
||||
$ tar xzf v0.23.0.tar.gz
|
||||
$ cd libgit2-0.23.0/
|
||||
$ git clone --depth=1 -b maint/v0.26 https://github.com/libgit2/libgit2.git
|
||||
$ cd libgit2
|
||||
$ cmake . -DSTDCALL=OFF -DCMAKE_INSTALL_PREFIX=$LIBGIT2 -G "Visual Studio 9 2008"
|
||||
$ cmake --build . --config release --target install
|
||||
$ ctest -v
|
||||
|
||||
At this point, you're ready to execute the generic pygit2 installation
|
||||
steps described above.
|
||||
At this point, you're ready to execute the generic `pygit2`
|
||||
installation steps described at the start of this page.
|
||||
|
||||
|
||||
Installing on OS X
|
||||
|
@ -132,6 +132,7 @@ them to the Git object database:
|
||||
|
||||
.. automethod:: pygit2.Repository.create_blob_fromworkdir
|
||||
.. automethod:: pygit2.Repository.create_blob_fromdisk
|
||||
.. automethod:: pygit2.Repository.create_blob_fromiobase
|
||||
|
||||
There are also some functions to calculate the id for a byte string without
|
||||
creating the blob object:
|
||||
@ -176,6 +177,7 @@ Tree entries
|
||||
.. autoattribute:: pygit2.TreeEntry.id
|
||||
.. autoattribute:: pygit2.TreeEntry.hex
|
||||
.. autoattribute:: pygit2.TreeEntry.filemode
|
||||
.. autoattribute:: pygit2.TreeEntry.type
|
||||
|
||||
.. method:: TreeEntry.__cmp__(TreeEntry)
|
||||
|
||||
@ -188,14 +190,14 @@ Example::
|
||||
6
|
||||
|
||||
>>> for entry in tree: # Iteration
|
||||
... print(entry.id, entry.name)
|
||||
... print(entry.id, entry.type, entry.name)
|
||||
...
|
||||
7151ca7cd3e59f3eab19c485cfbf3cb30928d7fa .gitignore
|
||||
c36f4cf1e38ec1bb9d9ad146ed572b89ecfc9f18 COPYING
|
||||
32b30b90b062f66957d6790c3c155c289c34424e README.md
|
||||
c87dae4094b3a6d10e08bc6c5ef1f55a7e448659 pygit2.c
|
||||
85a67270a49ef16cdd3d328f06a3e4b459f09b27 setup.py
|
||||
3d8985bbec338eb4d47c5b01b863ee89d044bd53 test
|
||||
7151ca7cd3e59f3eab19c485cfbf3cb30928d7fa blob .gitignore
|
||||
c36f4cf1e38ec1bb9d9ad146ed572b89ecfc9f18 blob COPYING
|
||||
32b30b90b062f66957d6790c3c155c289c34424e blob README.md
|
||||
c87dae4094b3a6d10e08bc6c5ef1f55a7e448659 blob pygit2.c
|
||||
85a67270a49ef16cdd3d328f06a3e4b459f09b27 blob setup.py
|
||||
3d8985bbec338eb4d47c5b01b863ee89d044bd53 tree test
|
||||
|
||||
>>> entry = tree['pygit2.c'] # Get an entry by name
|
||||
>>> entry
|
||||
|
@ -49,7 +49,7 @@ example `three-argument rebases`_.
|
||||
repo = pygit2.Repository('/path/to/repo')
|
||||
|
||||
cherry = repo.revparse_single('9e044d03c')
|
||||
basket = repo.lookup_branch('basket')
|
||||
basket = repo.branches.get('basket')
|
||||
|
||||
base = repo.merge_base(cherry.oid, basket.target)
|
||||
base_tree = cherry.parents[0].tree
|
||||
|
@ -4,15 +4,25 @@ References
|
||||
|
||||
.. contents::
|
||||
|
||||
.. automethod:: pygit2.Repository.listall_references
|
||||
.. automethod:: pygit2.Repository.lookup_reference
|
||||
.. autoclass:: pygit2.repository.References
|
||||
:members:
|
||||
:undoc-members:
|
||||
:special-members: __getitem__, __iter__, __contains__
|
||||
|
||||
|
||||
Example::
|
||||
|
||||
>>> all_refs = repo.listall_references()
|
||||
>>> all_refs = list(repo.references)
|
||||
|
||||
>>> master_ref = repo.lookup_reference("refs/heads/master")
|
||||
>>> commit = master_ref.get_object() # or repo[master_ref.target]
|
||||
|
||||
# Create a reference
|
||||
>>> ref = repo.references.create('refs/tags/version1', LAST_COMMIT)
|
||||
|
||||
# Delete a reference
|
||||
>>> repo.references.delete('refs/tags/version1')
|
||||
|
||||
|
||||
The Reference type
|
||||
====================
|
||||
@ -68,28 +78,33 @@ Branches
|
||||
Branches inherit from References, and additionally provide specialized
|
||||
accessors for some unique features.
|
||||
|
||||
.. automethod:: pygit2.Repository.listall_branches
|
||||
.. automethod:: pygit2.Repository.lookup_branch
|
||||
.. automethod:: pygit2.Repository.create_branch
|
||||
.. autoclass:: pygit2.repository.Branches
|
||||
:members:
|
||||
:undoc-members:
|
||||
:special-members: __getitem__, __iter__, __contains__
|
||||
|
||||
Example::
|
||||
|
||||
>>> local_branches = repo.listall_branches()
|
||||
>>> # equivalent to
|
||||
>>> local_branches = repo.listall_branches(pygit2.GIT_BRANCH_LOCAL)
|
||||
>>> # Listing all branches
|
||||
>>> branches_list = list(repo.branches)
|
||||
>>> # Local only
|
||||
>>> local_branches = list(repo.branches.local)
|
||||
>>> # Remote only
|
||||
>>> remote_branches = list(repo.branches.remote)
|
||||
|
||||
>>> remote_branches = repo.listall_branches(pygit2.GIT_BRANCH_REMOTE)
|
||||
>>> # Get a branch
|
||||
>>> branch = repo.branches['master']
|
||||
>>> other_branch = repo.branches['does-not-exist'] # Will raise a KeyError
|
||||
>>> other_branch = repo.branches.get('does-not-exist') # Returns None
|
||||
|
||||
>>> all_branches = repo.listall_branches(pygit2.GIT_BRANCH_REMOTE |
|
||||
pygit2.GIT_BRANCH_LOCAL)
|
||||
>>> remote_branch = repo.branches.remote['upstream/feature']
|
||||
|
||||
>>> master_branch = repo.lookup_branch('master')
|
||||
>>> # equivalent to
|
||||
>>> master_branch = repo.lookup_branch('master',
|
||||
pygit2.GIT_BRANCH_LOCAL)
|
||||
>>> # Create a local branch
|
||||
>>> new_branch = repo.branches.local.create('new-branch')
|
||||
|
||||
>>> And delete it
|
||||
>>> repo.branches.delete('new-branch')
|
||||
|
||||
>>> remote_branch = repo.lookup_branch('upstream/feature',
|
||||
pygit2.GIT_BRANCH_REMOTE)
|
||||
|
||||
The Branch type
|
||||
====================
|
||||
@ -98,17 +113,19 @@ The Branch type
|
||||
.. autoattribute:: pygit2.Branch.remote_name
|
||||
.. autoattribute:: pygit2.Branch.upstream
|
||||
.. autoattribute:: pygit2.Branch.upstream_name
|
||||
|
||||
.. automethod:: pygit2.Branch.rename
|
||||
.. automethod:: pygit2.Branch.delete
|
||||
.. automethod:: pygit2.Branch.is_head
|
||||
.. automethod:: pygit2.Branch.is_checked_out
|
||||
|
||||
The reference log
|
||||
====================
|
||||
|
||||
Example::
|
||||
|
||||
>>> head = repo.lookup_reference('refs/heads/master')
|
||||
>>> head = repo.references.get('refs/heads/master') # Returns None if not found
|
||||
>>> # Almost equivalent to
|
||||
>>> head = repo.references['refs/heads/master'] # Raises KeyError if not found
|
||||
>>> for entry in head.log():
|
||||
... print(entry.message)
|
||||
|
||||
|
@ -21,6 +21,12 @@ The Remote type
|
||||
.. autoclass:: pygit2.Remote
|
||||
:members:
|
||||
|
||||
The RemoteCallbacks type
|
||||
========================
|
||||
|
||||
.. autoclass:: pygit2.RemoteCallbacks
|
||||
:members:
|
||||
|
||||
The TransferProgress type
|
||||
===========================
|
||||
|
||||
@ -42,8 +48,6 @@ Refspecs objects are not constructed directly, but returned by
|
||||
Credentials
|
||||
================
|
||||
|
||||
.. automethod:: pygit2.Remote.credentials
|
||||
|
||||
There are two types of credentials: username/password and SSH key
|
||||
pairs. Both :py:class:`pygit2.UserPass` and :py:class:`pygit2.Keypair`
|
||||
are callable objects, with the appropriate signature for the
|
||||
|
@ -67,7 +67,11 @@ Below there are some general attributes and methods:
|
||||
.. autoattribute:: pygit2.Repository.default_signature
|
||||
.. automethod:: pygit2.Repository.read
|
||||
.. automethod:: pygit2.Repository.write
|
||||
.. automethod:: pygit2.Repository.ahead_behind
|
||||
.. automethod:: pygit2.Repository.create_reference
|
||||
.. automethod:: pygit2.Repository.describe
|
||||
.. automethod:: pygit2.Repository.path_is_ignored
|
||||
.. automethod:: pygit2.Repository.reset
|
||||
.. automethod:: pygit2.Repository.revert_commit
|
||||
.. automethod:: pygit2.Repository.state_cleanup
|
||||
.. automethod:: pygit2.Repository.write_archive
|
||||
.. automethod:: pygit2.Repository.ahead_behind
|
||||
|
@ -1,10 +1,12 @@
|
||||
**********************************************************************
|
||||
The submodule
|
||||
Submodules
|
||||
**********************************************************************
|
||||
|
||||
A submodule is a foreign repository that is embedded within a
|
||||
dedicated subdirectory of the repositories tree.
|
||||
|
||||
.. automethod:: pygit2.Repository.init_submodules
|
||||
.. automethod:: pygit2.Repository.update_submodules
|
||||
.. automethod:: pygit2.Repository.lookup_submodule
|
||||
.. automethod:: pygit2.Repository.listall_submodules
|
||||
|
||||
|
@ -71,3 +71,11 @@ Lower level API:
|
||||
.. automethod:: pygit2.Repository.checkout_head
|
||||
.. automethod:: pygit2.Repository.checkout_tree
|
||||
.. automethod:: pygit2.Repository.checkout_index
|
||||
|
||||
Stash
|
||||
====================
|
||||
|
||||
.. automethod:: pygit2.Repository.stash
|
||||
.. automethod:: pygit2.Repository.stash_apply
|
||||
.. automethod:: pygit2.Repository.stash_drop
|
||||
.. automethod:: pygit2.Repository.stash_pop
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -35,15 +35,15 @@ from _pygit2 import *
|
||||
from .blame import Blame, BlameHunk
|
||||
from .config import Config
|
||||
from .credentials import *
|
||||
from .errors import check_error
|
||||
from .errors import check_error, Passthrough
|
||||
from .ffi import ffi, C
|
||||
from .index import Index, IndexEntry
|
||||
from .remote import Remote, get_credentials
|
||||
from .remote import Remote, RemoteCallbacks, get_credentials
|
||||
from .repository import Repository
|
||||
from .settings import Settings
|
||||
from .submodule import Submodule
|
||||
from .utils import to_bytes, to_str
|
||||
from ._utils import __version__
|
||||
from ._build import __version__
|
||||
|
||||
|
||||
# Features
|
||||
@ -105,6 +105,9 @@ def init_repository(path, bare=False,
|
||||
See libgit2's documentation on git_repository_init_ext for further details.
|
||||
"""
|
||||
# Pre-process input parameters
|
||||
if path is None:
|
||||
raise TypeError('Expected string type for path, found None.')
|
||||
|
||||
if bare:
|
||||
flags |= GIT_REPOSITORY_INIT_BARE
|
||||
|
||||
@ -143,22 +146,6 @@ def init_repository(path, bare=False,
|
||||
# Ok
|
||||
return Repository(to_str(path))
|
||||
|
||||
|
||||
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
||||
'const char *username_from_url, unsigned int allowed_types,'
|
||||
'void *data)')
|
||||
def _credentials_cb(cred_out, url, username_from_url, allowed, data):
|
||||
d = ffi.from_handle(data)
|
||||
|
||||
try:
|
||||
ccred = get_credentials(d['credentials_cb'], url, username_from_url, allowed)
|
||||
cred_out[0] = ccred[0]
|
||||
except Exception as e:
|
||||
d['exception'] = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*git_repository_create_cb)(git_repository **out,'
|
||||
'const char *path, int bare, void *payload)')
|
||||
def _repository_create_cb(repo_out, path, bare, data):
|
||||
@ -189,24 +176,9 @@ def _remote_create_cb(remote_out, repo, name, url, data):
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*git_transport_certificate_check_cb)'
|
||||
'(git_cert *cert, int valid, const char *host, void *payload)')
|
||||
def _certificate_cb(cert_i, valid, host, data):
|
||||
d = ffi.from_handle(data)
|
||||
try:
|
||||
# python's parting is deep in the libraries and assumes an OpenSSL-owned cert
|
||||
val = d['certificate_cb'](None, bool(valid), ffi.string(host))
|
||||
if not val:
|
||||
return C.GIT_ECERTIFICATE
|
||||
except Exception as e:
|
||||
d['exception'] = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
def clone_repository(
|
||||
url, path, bare=False, repository=None, remote=None,
|
||||
checkout_branch=None, credentials=None, certificate=None):
|
||||
checkout_branch=None, callbacks=None):
|
||||
"""Clones a new Git repository from *url* in the given *path*.
|
||||
|
||||
Returns a Repository class pointing to the newly cloned repository.
|
||||
@ -224,11 +196,8 @@ def clone_repository(
|
||||
:param str checkout_branch: Branch to checkout after the
|
||||
clone. The default is to use the remote's default branch.
|
||||
|
||||
:param callable credentials: authentication to use if the remote
|
||||
requires it
|
||||
|
||||
:param callable certificate: callback to verify the host's
|
||||
certificate or fingerprint.
|
||||
:param RemoteCallbacks callbacks: object which implements the
|
||||
callbacks as methods.
|
||||
|
||||
:rtype: Repository
|
||||
|
||||
@ -240,8 +209,8 @@ def clone_repository(
|
||||
signature. The Remote it returns will be used instead of the default
|
||||
one.
|
||||
|
||||
The certificate callback has `(cert, valid, hostname) -> bool` as
|
||||
a signature. Return True to accept the connection, False to abort.
|
||||
The callbacks should be an object which inherits from
|
||||
`pyclass:RemoteCallbacks`.
|
||||
|
||||
"""
|
||||
|
||||
@ -252,10 +221,8 @@ def clone_repository(
|
||||
|
||||
# Data, let's use a dict as we don't really want much more
|
||||
d = {}
|
||||
d['credentials_cb'] = credentials
|
||||
d['repository_cb'] = repository
|
||||
d['remote_cb'] = remote
|
||||
d['certificate_cb'] = certificate
|
||||
d_handle = ffi.new_handle(d)
|
||||
|
||||
# Perform the initialization with the version we compiled
|
||||
@ -277,13 +244,11 @@ def clone_repository(
|
||||
|
||||
|
||||
opts.bare = bare
|
||||
if credentials:
|
||||
opts.fetch_opts.callbacks.credentials = _credentials_cb
|
||||
opts.fetch_opts.callbacks.payload = d_handle
|
||||
|
||||
if certificate:
|
||||
opts.fetch_opts.callbacks.certificate_check = _certificate_cb
|
||||
opts.fetch_opts.callbacks.payload = d_handle
|
||||
if callbacks is None:
|
||||
callbacks = RemoteCallbacks()
|
||||
|
||||
callbacks._fill_fetch_options(opts.fetch_opts)
|
||||
|
||||
err = C.git_clone(crepo, to_bytes(url), to_bytes(path), opts)
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -26,23 +26,18 @@
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""
|
||||
This is an special module, it provides stuff used by setup.py and by
|
||||
pygit2 at run-time.
|
||||
This is an special module, it provides stuff used by setup.py at build time.
|
||||
But also used by pygit2 at run time.
|
||||
"""
|
||||
|
||||
# Import from the Standard Library
|
||||
from binascii import crc32
|
||||
import codecs
|
||||
import os
|
||||
from os import getenv
|
||||
from os.path import abspath, dirname
|
||||
import sys
|
||||
|
||||
|
||||
#
|
||||
# The version number of pygit2
|
||||
#
|
||||
__version__ = '0.23.0'
|
||||
__version__ = '0.26.0'
|
||||
|
||||
|
||||
#
|
||||
@ -67,44 +62,3 @@ def get_libgit2_paths():
|
||||
os.path.join(libgit2_path, 'include'),
|
||||
getenv('LIBGIT2_LIB', os.path.join(libgit2_path, 'lib')),
|
||||
)
|
||||
|
||||
|
||||
#
|
||||
# Loads the cffi extension
|
||||
#
|
||||
def get_ffi():
|
||||
import cffi
|
||||
|
||||
ffi = cffi.FFI()
|
||||
|
||||
# Load C definitions
|
||||
if getattr(sys, 'frozen', False):
|
||||
if hasattr(sys, '_MEIPASS'):
|
||||
dir_path = sys._MEIPASS
|
||||
else:
|
||||
dir_path = dirname(abspath(sys.executable))
|
||||
else:
|
||||
dir_path = dirname(abspath(__file__))
|
||||
|
||||
decl_path = os.path.join(dir_path, 'decl.h')
|
||||
with codecs.open(decl_path, 'r', 'utf-8') as header:
|
||||
ffi.cdef(header.read())
|
||||
|
||||
# The modulename
|
||||
# Simplified version of what cffi does: remove kwargs and vengine
|
||||
preamble = "#include <git2.h>"
|
||||
key = [sys.version[:3], cffi.__version__, preamble] + ffi._cdefsources
|
||||
key = '\x00'.join(key)
|
||||
if sys.version_info >= (3,):
|
||||
key = key.encode('utf-8')
|
||||
k1 = hex(crc32(key[0::2]) & 0xffffffff).lstrip('0x').rstrip('L')
|
||||
k2 = hex(crc32(key[1::2]) & 0xffffffff).lstrip('0').rstrip('L')
|
||||
modulename = 'pygit2_cffi_%s%s' % (k1, k2)
|
||||
|
||||
# Load extension module
|
||||
libgit2_bin, libgit2_include, libgit2_lib = get_libgit2_paths()
|
||||
C = ffi.verify(preamble, modulename=modulename, libraries=["git2"],
|
||||
include_dirs=[libgit2_include], library_dirs=[libgit2_lib])
|
||||
|
||||
# Ok
|
||||
return ffi, C
|
76
pygit2/_run.py
Normal file
76
pygit2/_run.py
Normal file
@ -0,0 +1,76 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# In addition to the permissions in the GNU General Public License,
|
||||
# the authors give you unlimited permission to link the compiled
|
||||
# version of this file into combinations with other programs,
|
||||
# and to distribute those combinations without any restriction
|
||||
# coming from the use of this file. (The General Public License
|
||||
# restrictions do apply in other respects; for example, they cover
|
||||
# modification of the file, and distribution when not linked into
|
||||
# a combined executable.)
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""
|
||||
This is an special module, it provides stuff used by by pygit2 at run-time.
|
||||
"""
|
||||
|
||||
# Import from the Standard Library
|
||||
import codecs
|
||||
import os
|
||||
from os.path import abspath, dirname
|
||||
import sys
|
||||
|
||||
# Import from cffi
|
||||
from cffi import FFI
|
||||
|
||||
# Import from pygit2
|
||||
from _build import get_libgit2_paths
|
||||
|
||||
|
||||
# C_HEADER_SRC
|
||||
if getattr(sys, 'frozen', False):
|
||||
dir_path = getattr(sys, '_MEIPASS', None)
|
||||
if dir_path is None:
|
||||
dir_path = dirname(abspath(sys.executable))
|
||||
else:
|
||||
dir_path = dirname(abspath(__file__))
|
||||
|
||||
decl_path = os.path.join(dir_path, 'decl.h')
|
||||
with codecs.open(decl_path, 'r', 'utf-8') as header:
|
||||
C_HEADER_SRC = header.read()
|
||||
|
||||
# C_KEYWORDS
|
||||
libgit2_bin, libgit2_include, libgit2_lib = get_libgit2_paths()
|
||||
C_KEYWORDS = dict(libraries=['git2'],
|
||||
library_dirs=[libgit2_lib],
|
||||
include_dirs=[libgit2_include])
|
||||
|
||||
# preamble
|
||||
preamble = "#include <git2.h>"
|
||||
|
||||
# ffi
|
||||
ffi = FFI()
|
||||
set_source = getattr(ffi, 'set_source', None)
|
||||
if set_source is not None:
|
||||
set_source("pygit2._libgit2", preamble, **C_KEYWORDS)
|
||||
|
||||
ffi.cdef(C_HEADER_SRC)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
ffi.compile()
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
200
pygit2/decl.h
200
pygit2/decl.h
@ -54,6 +54,16 @@ typedef enum {
|
||||
GIT_EINVALIDSPEC = -12,
|
||||
GIT_ECONFLICT = -13,
|
||||
GIT_ELOCKED = -14,
|
||||
GIT_EMODIFIED = -15,
|
||||
GIT_EAUTH = -16,
|
||||
GIT_ECERTIFICATE = -17,
|
||||
GIT_EAPPLIED = -18,
|
||||
GIT_EPEEL = -19,
|
||||
GIT_EEOF = -20,
|
||||
GIT_EINVALID = -21,
|
||||
GIT_EUNCOMMITTED = -22,
|
||||
GIT_EDIRECTORY = -23,
|
||||
GIT_EMERGECONFLICT = -24,
|
||||
|
||||
GIT_PASSTHROUGH = -30,
|
||||
GIT_ITEROVER = -31,
|
||||
@ -131,21 +141,21 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
git_cert_t cert_type;
|
||||
} git_cert;
|
||||
|
||||
typedef struct {
|
||||
git_cert parent;
|
||||
git_cert_ssh_t type;
|
||||
unsigned char hash_md5[16];
|
||||
unsigned char hash_sha1[20];
|
||||
} git_cert_hostkey;
|
||||
|
||||
typedef struct {
|
||||
git_cert_t cert_type;
|
||||
git_cert parent;
|
||||
void *data;
|
||||
size_t len;
|
||||
} git_cert_x509;
|
||||
|
||||
typedef struct {
|
||||
git_cert_t cert_type;
|
||||
} git_cert;
|
||||
|
||||
typedef int (*git_transport_message_cb)(const char *str, int len, void *data);
|
||||
typedef int (*git_cred_acquire_cb)(
|
||||
git_cred **cred,
|
||||
@ -197,10 +207,30 @@ struct git_remote_callbacks {
|
||||
|
||||
typedef struct git_remote_callbacks git_remote_callbacks;
|
||||
|
||||
typedef enum {
|
||||
GIT_PROXY_NONE,
|
||||
GIT_PROXY_AUTO,
|
||||
GIT_PROXY_SPECIFIED,
|
||||
} git_proxy_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
git_proxy_t type;
|
||||
const char *url;
|
||||
git_cred_acquire_cb credentials;
|
||||
git_transport_certificate_check_cb certificate_check;
|
||||
void *payload;
|
||||
} git_proxy_options;
|
||||
|
||||
#define GIT_PROXY_OPTIONS_VERSION ...
|
||||
int git_proxy_init_options(git_proxy_options *opts, unsigned int version);
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
unsigned int pb_parallelism;
|
||||
git_remote_callbacks callbacks;
|
||||
git_proxy_options proxy_opts;
|
||||
git_strarray custom_headers;
|
||||
} git_push_options;
|
||||
|
||||
#define GIT_PUSH_OPTIONS_VERSION ...
|
||||
@ -225,6 +255,8 @@ typedef struct {
|
||||
git_fetch_prune_t prune;
|
||||
int update_fetchhead;
|
||||
git_remote_autotag_option_t download_tags;
|
||||
git_proxy_options proxy_opts;
|
||||
git_strarray custom_headers;
|
||||
} git_fetch_options;
|
||||
|
||||
#define GIT_FETCH_OPTIONS_VERSION ...
|
||||
@ -336,13 +368,20 @@ typedef int (*git_diff_notify_cb)(
|
||||
const char *matched_pathspec,
|
||||
void *payload);
|
||||
|
||||
typedef int (*git_diff_progress_cb)(
|
||||
const git_diff *diff_so_far,
|
||||
const char *old_path,
|
||||
const char *new_path,
|
||||
void *payload);
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
uint32_t flags;
|
||||
git_submodule_ignore_t ignore_submodules;
|
||||
git_strarray pathspec;
|
||||
git_diff_notify_cb notify_cb;
|
||||
void *notify_payload;
|
||||
git_diff_notify_cb notify_cb;
|
||||
git_diff_progress_cb progress_cb;
|
||||
void *payload;
|
||||
uint32_t context_lines;
|
||||
uint32_t interhunk_lines;
|
||||
uint16_t id_abbrev;
|
||||
@ -371,7 +410,16 @@ int git_diff_tree_to_index(git_diff **diff, git_repository *repo, git_tree *old_
|
||||
* git_checkout
|
||||
*/
|
||||
|
||||
typedef enum { ... } git_checkout_notify_t;
|
||||
typedef enum {
|
||||
GIT_CHECKOUT_NOTIFY_NONE = 0,
|
||||
GIT_CHECKOUT_NOTIFY_CONFLICT = 1,
|
||||
GIT_CHECKOUT_NOTIFY_DIRTY = 2,
|
||||
GIT_CHECKOUT_NOTIFY_UPDATED = 4,
|
||||
GIT_CHECKOUT_NOTIFY_UNTRACKED = 8,
|
||||
GIT_CHECKOUT_NOTIFY_IGNORED = 16,
|
||||
|
||||
GIT_CHECKOUT_NOTIFY_ALL = 0x0FFFF
|
||||
} git_checkout_notify_t;
|
||||
|
||||
typedef int (*git_checkout_notify_cb)(
|
||||
git_checkout_notify_t why,
|
||||
@ -478,11 +526,12 @@ typedef ... git_config;
|
||||
typedef ... git_config_iterator;
|
||||
|
||||
typedef enum {
|
||||
GIT_CONFIG_LEVEL_SYSTEM = 1,
|
||||
GIT_CONFIG_LEVEL_XDG = 2,
|
||||
GIT_CONFIG_LEVEL_GLOBAL = 3,
|
||||
GIT_CONFIG_LEVEL_LOCAL = 4,
|
||||
GIT_CONFIG_LEVEL_APP = 5,
|
||||
GIT_CONFIG_LEVEL_PROGRAMDATA = 1,
|
||||
GIT_CONFIG_LEVEL_SYSTEM = 2,
|
||||
GIT_CONFIG_LEVEL_XDG = 3,
|
||||
GIT_CONFIG_LEVEL_GLOBAL = 4,
|
||||
GIT_CONFIG_LEVEL_LOCAL = 5,
|
||||
GIT_CONFIG_LEVEL_APP = 6,
|
||||
GIT_CONFIG_HIGHEST_LEVEL = -1,
|
||||
} git_config_level_t;
|
||||
|
||||
@ -671,22 +720,22 @@ typedef struct git_blame_options {
|
||||
uint16_t min_match_characters;
|
||||
git_oid newest_commit;
|
||||
git_oid oldest_commit;
|
||||
uint32_t min_line;
|
||||
uint32_t max_line;
|
||||
size_t min_line;
|
||||
size_t max_line;
|
||||
} git_blame_options;
|
||||
|
||||
#define GIT_BLAME_OPTIONS_VERSION ...
|
||||
|
||||
typedef struct git_blame_hunk {
|
||||
uint16_t lines_in_hunk;
|
||||
size_t lines_in_hunk;
|
||||
|
||||
git_oid final_commit_id;
|
||||
uint16_t final_start_line_number;
|
||||
size_t final_start_line_number;
|
||||
git_signature *final_signature;
|
||||
|
||||
git_oid orig_commit_id;
|
||||
const char *orig_path;
|
||||
uint16_t orig_start_line_number;
|
||||
size_t orig_start_line_number;
|
||||
git_signature *orig_signature;
|
||||
|
||||
char boundary;
|
||||
@ -695,7 +744,7 @@ typedef struct git_blame_hunk {
|
||||
int git_blame_init_options(git_blame_options *opts, unsigned int version);
|
||||
uint32_t git_blame_get_hunk_count(git_blame *blame);
|
||||
const git_blame_hunk *git_blame_get_hunk_byindex(git_blame *blame, uint32_t index);
|
||||
const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, uint32_t lineno);
|
||||
const git_blame_hunk *git_blame_get_hunk_byline(git_blame *blame, size_t lineno);
|
||||
int git_blame_file(git_blame **out, git_repository *repo, const char *path, git_blame_options *options);
|
||||
void git_blame_free(git_blame *blame);
|
||||
|
||||
@ -703,7 +752,12 @@ void git_blame_free(git_blame *blame);
|
||||
* Merging
|
||||
*/
|
||||
|
||||
typedef enum { ... } git_merge_tree_flag_t;
|
||||
typedef enum {
|
||||
GIT_MERGE_FIND_RENAMES = 1,
|
||||
GIT_MERGE_FAIL_ON_CONFLICT = 2,
|
||||
GIT_MERGE_SKIP_REUC = 4,
|
||||
GIT_MERGE_NO_RECURSIVE = 8,
|
||||
} git_merge_flag_t;
|
||||
|
||||
typedef enum {
|
||||
GIT_MERGE_FILE_FAVOR_NORMAL = 0,
|
||||
@ -714,10 +768,12 @@ typedef enum {
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
git_merge_tree_flag_t tree_flags;
|
||||
git_merge_flag_t flags;
|
||||
unsigned int rename_threshold;
|
||||
unsigned int target_limit;
|
||||
git_diff_similarity_metric *metric;
|
||||
unsigned int recursion_limit;
|
||||
const char *default_driver;
|
||||
git_merge_file_favor_t file_favor;
|
||||
unsigned int file_flags;
|
||||
} git_merge_options;
|
||||
@ -737,7 +793,12 @@ typedef enum {
|
||||
GIT_MERGE_FILE_STYLE_MERGE = 1,
|
||||
GIT_MERGE_FILE_STYLE_DIFF3 = 2,
|
||||
GIT_MERGE_FILE_SIMPLIFY_ALNUM = 4,
|
||||
} git_merge_file_flags_t;
|
||||
GIT_MERGE_FILE_IGNORE_WHITESPACE = 8,
|
||||
GIT_MERGE_FILE_IGNORE_WHITESPACE_CHANGE = 16,
|
||||
GIT_MERGE_FILE_IGNORE_WHITESPACE_EOL = 32,
|
||||
GIT_MERGE_FILE_DIFF_PATIENCE = 64,
|
||||
GIT_MERGE_FILE_DIFF_MINIMAL = 128,
|
||||
} git_merge_file_flag_t;
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
@ -745,7 +806,7 @@ typedef struct {
|
||||
const char *our_label;
|
||||
const char *their_label;
|
||||
git_merge_file_favor_t favor;
|
||||
git_merge_file_flags_t flags;
|
||||
git_merge_file_flag_t flags;
|
||||
} git_merge_file_options;
|
||||
|
||||
#define GIT_MERGE_OPTIONS_VERSION ...
|
||||
@ -756,6 +817,97 @@ int git_merge_trees(git_index **out, git_repository *repo, const git_tree *ances
|
||||
int git_merge_file_from_index(git_merge_file_result *out, git_repository *repo, const git_index_entry *ancestor, const git_index_entry *ours, const git_index_entry *theirs, const git_merge_file_options *opts);
|
||||
void git_merge_file_result_free(git_merge_file_result *result);
|
||||
|
||||
/*
|
||||
* git_stash
|
||||
*/
|
||||
|
||||
typedef int (*git_stash_cb)(
|
||||
size_t index, const char* message, const git_oid *stash_id, void *payload);
|
||||
|
||||
typedef enum {
|
||||
GIT_STASH_APPLY_PROGRESS_NONE = 0,
|
||||
GIT_STASH_APPLY_PROGRESS_LOADING_STASH = 1,
|
||||
GIT_STASH_APPLY_PROGRESS_ANALYZE_INDEX = 2,
|
||||
GIT_STASH_APPLY_PROGRESS_ANALYZE_MODIFIED = 3,
|
||||
GIT_STASH_APPLY_PROGRESS_ANALYZE_UNTRACKED = 4,
|
||||
GIT_STASH_APPLY_PROGRESS_CHECKOUT_UNTRACKED = 5,
|
||||
GIT_STASH_APPLY_PROGRESS_CHECKOUT_MODIFIED = 6,
|
||||
GIT_STASH_APPLY_PROGRESS_DONE = 7,
|
||||
} git_stash_apply_progress_t;
|
||||
|
||||
typedef int (*git_stash_apply_progress_cb)(
|
||||
git_stash_apply_progress_t progress, void *payload);
|
||||
|
||||
typedef enum {
|
||||
GIT_STASH_DEFAULT = 0,
|
||||
GIT_STASH_KEEP_INDEX = 1,
|
||||
GIT_STASH_INCLUDE_UNTRACKED = 2,
|
||||
GIT_STASH_INCLUDE_IGNORED = 4,
|
||||
} git_stash_flags;
|
||||
|
||||
typedef enum {
|
||||
GIT_STASH_APPLY_DEFAULT = 0,
|
||||
GIT_STASH_APPLY_REINSTATE_INDEX = 1,
|
||||
} git_stash_apply_flags;
|
||||
|
||||
typedef struct git_stash_apply_options {
|
||||
unsigned int version;
|
||||
git_stash_apply_flags flags;
|
||||
git_checkout_options checkout_options;
|
||||
git_stash_apply_progress_cb progress_cb;
|
||||
void *progress_payload;
|
||||
} git_stash_apply_options;
|
||||
|
||||
#define GIT_STASH_APPLY_OPTIONS_VERSION ...
|
||||
|
||||
int git_stash_save(git_oid *out, git_repository *repo, const git_signature *stasher, const char *message, uint32_t flags);
|
||||
int git_stash_apply_init_options(git_stash_apply_options *opts, unsigned int version);
|
||||
int git_stash_apply(git_repository *repo, size_t index, const git_stash_apply_options *options);
|
||||
int git_stash_foreach(git_repository *repo, git_stash_cb callback, void *payload);
|
||||
int git_stash_drop(git_repository *repo, size_t index);
|
||||
int git_stash_pop(git_repository *repo, size_t index, const git_stash_apply_options *options);
|
||||
|
||||
/*
|
||||
* Describe
|
||||
*/
|
||||
|
||||
typedef enum {
|
||||
GIT_DESCRIBE_DEFAULT,
|
||||
GIT_DESCRIBE_TAGS,
|
||||
GIT_DESCRIBE_ALL,
|
||||
} git_describe_strategy_t;
|
||||
|
||||
typedef struct git_describe_options {
|
||||
unsigned int version;
|
||||
unsigned int max_candidates_tags;
|
||||
unsigned int describe_strategy;
|
||||
const char *pattern;
|
||||
int only_follow_first_parent;
|
||||
int show_commit_oid_as_fallback;
|
||||
} git_describe_options;
|
||||
|
||||
#define GIT_DESCRIBE_OPTIONS_VERSION ...
|
||||
|
||||
int git_describe_init_options(git_describe_options *opts, unsigned int version);
|
||||
|
||||
typedef struct {
|
||||
unsigned int version;
|
||||
unsigned int abbreviated_size;
|
||||
int always_use_long_format;
|
||||
const char *dirty_suffix;
|
||||
} git_describe_format_options;
|
||||
|
||||
#define GIT_DESCRIBE_FORMAT_OPTIONS_VERSION ...
|
||||
|
||||
int git_describe_init_format_options(git_describe_format_options *opts, unsigned int version);
|
||||
|
||||
typedef ... git_describe_result;
|
||||
|
||||
int git_describe_commit(git_describe_result **result, git_object *committish, git_describe_options *opts);
|
||||
int git_describe_workdir(git_describe_result **out, git_repository *repo, git_describe_options *opts);
|
||||
int git_describe_format(git_buf *out, const git_describe_result *result, const git_describe_format_options *opts);
|
||||
void git_describe_result_free(git_describe_result *result);
|
||||
|
||||
#define GIT_ATTR_CHECK_FILE_THEN_INDEX ...
|
||||
#define GIT_ATTR_CHECK_INDEX_THEN_FILE ...
|
||||
#define GIT_ATTR_CHECK_INDEX_ONLY ...
|
||||
@ -770,3 +922,5 @@ typedef enum {
|
||||
|
||||
int git_attr_get(const char **value_out, git_repository *repo, uint32_t flags, const char *path, const char *name);
|
||||
git_attr_t git_attr_value(const char *attr);
|
||||
|
||||
int git_revert_commit(git_index **out, git_repository *repo, git_commit *revert_commit, git_commit *our_commit, unsigned int mainline, const git_merge_options *merge_options);
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -40,7 +40,7 @@ def check_error(err, io=False):
|
||||
# Error message
|
||||
giterr = C.giterr_last()
|
||||
if giterr != ffi.NULL:
|
||||
message = ffi.string(giterr.message).decode()
|
||||
message = ffi.string(giterr.message).decode('utf8')
|
||||
else:
|
||||
message = "err %d (no message provided)" % err
|
||||
|
||||
@ -62,3 +62,8 @@ def check_error(err, io=False):
|
||||
|
||||
# Generic Git error
|
||||
raise GitError(message)
|
||||
|
||||
# Indicate that we want libgit2 to pretend a function was not set
|
||||
class Passthrough(Exception):
|
||||
def __init__(self):
|
||||
super(Passthrough, self).__init__( "The function asked for pass-through")
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -29,7 +29,8 @@
|
||||
from __future__ import absolute_import
|
||||
|
||||
# Import from pygit2
|
||||
from ._utils import get_ffi
|
||||
|
||||
|
||||
ffi, C = get_ffi()
|
||||
try:
|
||||
from ._libgit2 import ffi, lib as C
|
||||
except ImportError:
|
||||
from ._run import ffi, preamble, C_KEYWORDS
|
||||
C = ffi.verify(preamble, **C_KEYWORDS)
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -28,6 +28,8 @@
|
||||
# Import from the future
|
||||
from __future__ import absolute_import, unicode_literals
|
||||
|
||||
import weakref
|
||||
|
||||
# Import from pygit2
|
||||
from _pygit2 import Oid, Tree, Diff
|
||||
from .errors import check_error
|
||||
@ -48,6 +50,7 @@ class Index(object):
|
||||
err = C.git_index_open(cindex, to_bytes(path))
|
||||
check_error(err)
|
||||
|
||||
self._repo = None
|
||||
self._index = cindex[0]
|
||||
self._cindex = cindex
|
||||
|
||||
@ -125,14 +128,15 @@ class Index(object):
|
||||
The tree will be read recursively and all its children will also be
|
||||
inserted into the Index.
|
||||
"""
|
||||
repo = self._repo
|
||||
if is_string(tree):
|
||||
tree = self._repo[tree]
|
||||
tree = repo[tree]
|
||||
|
||||
if isinstance(tree, Oid):
|
||||
if not hasattr(self, '_repo'):
|
||||
if repo is None:
|
||||
raise TypeError("id given but no associated repository")
|
||||
|
||||
tree = self._repo[tree]
|
||||
tree = repo[tree]
|
||||
elif not isinstance(tree, Tree):
|
||||
raise TypeError("argument must be Oid or Tree")
|
||||
|
||||
@ -153,6 +157,9 @@ class Index(object):
|
||||
It returns the id of the resulting tree.
|
||||
"""
|
||||
coid = ffi.new('git_oid *')
|
||||
|
||||
repo = repo or self._repo
|
||||
|
||||
if repo:
|
||||
err = C.git_index_write_tree_to(coid, self._index, repo._repo)
|
||||
else:
|
||||
@ -214,7 +221,8 @@ class Index(object):
|
||||
interhunk_lines: the maximum number of unchanged lines between hunk
|
||||
boundaries before the hunks will be merged into a one
|
||||
"""
|
||||
if not hasattr(self, '_repo'):
|
||||
repo = self._repo
|
||||
if repo is None:
|
||||
raise ValueError('diff needs an associated repository')
|
||||
|
||||
copts = ffi.new('git_diff_options *')
|
||||
@ -226,11 +234,11 @@ class Index(object):
|
||||
copts.interhunk_lines = interhunk_lines
|
||||
|
||||
cdiff = ffi.new('git_diff **')
|
||||
err = C.git_diff_index_to_workdir(cdiff, self._repo._repo,
|
||||
self._index, copts)
|
||||
err = C.git_diff_index_to_workdir(cdiff, repo._repo, self._index,
|
||||
copts)
|
||||
check_error(err)
|
||||
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), self._repo)
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), repo)
|
||||
|
||||
def diff_to_tree(self, tree, flags=0, context_lines=3, interhunk_lines=0):
|
||||
"""Diff the index against a tree. Return a <Diff> object with the
|
||||
@ -248,8 +256,8 @@ class Index(object):
|
||||
interhunk_lines: the maximum number of unchanged lines between hunk
|
||||
boundaries before the hunks will be merged into a one.
|
||||
"""
|
||||
|
||||
if not hasattr(self, '_repo'):
|
||||
repo = self._repo
|
||||
if repo is None:
|
||||
raise ValueError('diff needs an associated repository')
|
||||
|
||||
if not isinstance(tree, Tree):
|
||||
@ -267,11 +275,11 @@ class Index(object):
|
||||
ffi.buffer(ctree)[:] = tree._pointer[:]
|
||||
|
||||
cdiff = ffi.new('git_diff **')
|
||||
err = C.git_diff_tree_to_index(cdiff, self._repo._repo, ctree[0],
|
||||
err = C.git_diff_tree_to_index(cdiff, repo._repo, ctree[0],
|
||||
self._index, copts)
|
||||
check_error(err)
|
||||
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), self._repo)
|
||||
return Diff.from_c(bytes(ffi.buffer(cdiff)[:]), repo)
|
||||
|
||||
|
||||
#
|
||||
@ -302,10 +310,12 @@ class Index(object):
|
||||
self._conflicts = None
|
||||
return None
|
||||
|
||||
if self._conflicts is None:
|
||||
self._conflicts = ConflictCollection(self)
|
||||
if self._conflicts is None or self._conflicts() is None:
|
||||
conflicts = ConflictCollection(self)
|
||||
self._conflicts = weakref.ref(conflicts)
|
||||
return conflicts
|
||||
|
||||
return self._conflicts
|
||||
return self._conflicts()
|
||||
|
||||
|
||||
class IndexEntry(object):
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
349
pygit2/remote.py
349
pygit2/remote.py
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -30,9 +30,8 @@ from __future__ import absolute_import
|
||||
|
||||
# Import from pygit2
|
||||
from _pygit2 import Oid
|
||||
from .errors import check_error, GitError
|
||||
from .errors import check_error, Passthrough
|
||||
from .ffi import ffi, C
|
||||
from .credentials import KeypairFromAgent
|
||||
from .refspec import Refspec
|
||||
from .utils import to_bytes, strarray_to_strings, StrArray
|
||||
|
||||
@ -71,7 +70,27 @@ class TransferProgress(object):
|
||||
""""Number of bytes received up to now"""
|
||||
|
||||
|
||||
class Remote(object):
|
||||
class RemoteCallbacks(object):
|
||||
"""Base class for pygit2 remote callbacks.
|
||||
|
||||
Inherit from this class and override the callbacks which you want to use
|
||||
in your class, which you can then pass to the network operations.
|
||||
"""
|
||||
|
||||
def __init__(self, credentials=None, certificate=None):
|
||||
"""Initialize some callbacks in-line
|
||||
|
||||
Use this constructor to provide credentials and certificate
|
||||
callbacks in-line, instead of defining your own class for these ones.
|
||||
|
||||
You can e.g. also pass in one of the credential objects as 'credentials'
|
||||
instead of creating a function which returns a hard-coded object.
|
||||
"""
|
||||
|
||||
if credentials is not None:
|
||||
self.credentials = credentials
|
||||
if certificate is not None:
|
||||
self.certificate = certificate
|
||||
|
||||
def sideband_progress(self, string):
|
||||
"""Progress output callback
|
||||
@ -80,7 +99,6 @@ class Remote(object):
|
||||
|
||||
:param str string: Progress output from the remote
|
||||
"""
|
||||
pass
|
||||
|
||||
def credentials(self, url, username_from_url, allowed_types):
|
||||
"""Credentials callback
|
||||
@ -100,7 +118,26 @@ class Remote(object):
|
||||
|
||||
Return value: credential
|
||||
"""
|
||||
pass
|
||||
raise Passthrough
|
||||
|
||||
def certificate_check(self, certificate, valid, host):
|
||||
"""Certificate callback
|
||||
|
||||
Override with your own function to determine whether the accept
|
||||
the server's certificate.
|
||||
|
||||
:param None certificate: The certificate. It is currently always None
|
||||
while we figure out how to represent it cross-platform
|
||||
|
||||
:param bool valid: Whether the TLS/SSH library thinks the certificate
|
||||
is valid
|
||||
|
||||
:param str host: The hostname we want to connect to
|
||||
|
||||
Return value: True to connect, False to abort
|
||||
"""
|
||||
|
||||
raise Passthrough
|
||||
|
||||
def transfer_progress(self, stats):
|
||||
"""Transfer progress callback
|
||||
@ -109,7 +146,6 @@ class Remote(object):
|
||||
|
||||
:param TransferProgress stats: The progress up to now
|
||||
"""
|
||||
pass
|
||||
|
||||
def update_tips(self, refname, old, new):
|
||||
"""Update tips callabck
|
||||
@ -131,6 +167,159 @@ class Remote(object):
|
||||
:param str messsage: rejection message from the remote. If None, the update was accepted.
|
||||
"""
|
||||
|
||||
def _fill_fetch_options(self, fetch_opts):
|
||||
fetch_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
fetch_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
fetch_opts.callbacks.update_tips = self._update_tips_cb
|
||||
fetch_opts.callbacks.credentials = self._credentials_cb
|
||||
fetch_opts.callbacks.certificate_check = self._certificate_cb
|
||||
# We need to make sure that this handle stays alive
|
||||
self._self_handle = ffi.new_handle(self)
|
||||
fetch_opts.callbacks.payload = self._self_handle
|
||||
|
||||
self._stored_exception = None
|
||||
|
||||
def _fill_push_options(self, push_opts):
|
||||
push_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
push_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
push_opts.callbacks.update_tips = self._update_tips_cb
|
||||
push_opts.callbacks.credentials = self._credentials_cb
|
||||
push_opts.callbacks.certificate_check = self._certificate_cb
|
||||
push_opts.callbacks.push_update_reference = self._push_update_reference_cb
|
||||
# We need to make sure that this handle stays alive
|
||||
self._self_handle = ffi.new_handle(self)
|
||||
push_opts.callbacks.payload = self._self_handle
|
||||
|
||||
# These functions exist to be called by the git_remote as
|
||||
# callbacks. They proxy the call to whatever the user set
|
||||
|
||||
@ffi.callback('git_transfer_progress_cb')
|
||||
def _transfer_progress_cb(stats_ptr, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
transfer_progress = getattr(self, 'transfer_progress', None)
|
||||
if not transfer_progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
transfer_progress(TransferProgress(stats_ptr))
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('git_transport_message_cb')
|
||||
def _sideband_progress_cb(string, length, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
progress = getattr(self, 'progress', None)
|
||||
if not progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = ffi.string(string, length).decode()
|
||||
progress(s)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*update_tips)(const char *refname, const git_oid *a,'
|
||||
'const git_oid *b, void *data)')
|
||||
def _update_tips_cb(refname, a, b, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
update_tips = getattr(self, 'update_tips', None)
|
||||
if not update_tips:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = maybe_string(refname)
|
||||
a = Oid(raw=bytes(ffi.buffer(a)[:]))
|
||||
b = Oid(raw=bytes(ffi.buffer(b)[:]))
|
||||
|
||||
update_tips(s, a, b)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback("int (*push_update_reference)(const char *ref, const char *msg, void *data)")
|
||||
def _push_update_reference_cb(ref, msg, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
push_update_reference = getattr(self, 'push_update_reference', None)
|
||||
if not push_update_reference:
|
||||
return 0
|
||||
|
||||
try:
|
||||
refname = ffi.string(ref)
|
||||
message = maybe_string(msg)
|
||||
push_update_reference(refname, message)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
||||
'const char *username_from_url, unsigned int allowed_types,'
|
||||
'void *data)')
|
||||
def _credentials_cb(cred_out, url, username, allowed, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
credentials = getattr(self, 'credentials', None)
|
||||
if not credentials:
|
||||
return 0
|
||||
|
||||
try:
|
||||
ccred = get_credentials(credentials, url, username, allowed)
|
||||
cred_out[0] = ccred[0]
|
||||
except Passthrough as e:
|
||||
return C.GIT_PASSTHROUGH
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*git_transport_certificate_check_cb)'
|
||||
'(git_cert *cert, int valid, const char *host, void *payload)')
|
||||
def _certificate_cb(cert_i, valid, host, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
# We want to simulate what should happen if libgit2 supported pass-through for
|
||||
# this callback. For SSH, 'valid' is always False, because it doesn't look
|
||||
# at known_hosts, but we do want to let it through in order to do what libgit2 would
|
||||
# if the callback were not set.
|
||||
try:
|
||||
is_ssh = cert_i.cert_type == C.GIT_CERT_HOSTKEY_LIBSSH2
|
||||
|
||||
certificate_check = getattr(self, 'certificate_check', None)
|
||||
if not certificate_check:
|
||||
raise Passthrough
|
||||
|
||||
# python's parsing is deep in the libraries and assumes an OpenSSL-owned cert
|
||||
val = certificate_check(None, bool(valid), ffi.string(host))
|
||||
if not val:
|
||||
return C.GIT_ECERTIFICATE
|
||||
except Passthrough as e:
|
||||
if is_ssh:
|
||||
return 0
|
||||
elif valid:
|
||||
return 0
|
||||
else:
|
||||
return C.GIT_ECERTIFICATE
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
class Remote(object):
|
||||
def __init__(self, repo, ptr):
|
||||
"""The constructor is for internal use only"""
|
||||
|
||||
@ -165,7 +354,7 @@ class Remote(object):
|
||||
err = C.git_remote_save(self._remote)
|
||||
check_error(err)
|
||||
|
||||
def fetch(self, refspecs=None, message=None):
|
||||
def fetch(self, refspecs=None, message=None, callbacks=None):
|
||||
"""Perform a fetch against this remote. Returns a <TransferProgress>
|
||||
object.
|
||||
"""
|
||||
@ -173,24 +362,19 @@ class Remote(object):
|
||||
fetch_opts = ffi.new('git_fetch_options *')
|
||||
err = C.git_fetch_init_options(fetch_opts, C.GIT_FETCH_OPTIONS_VERSION)
|
||||
|
||||
fetch_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
fetch_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
fetch_opts.callbacks.update_tips = self._update_tips_cb
|
||||
fetch_opts.callbacks.credentials = self._credentials_cb
|
||||
# We need to make sure that this handle stays alive
|
||||
self._self_handle = ffi.new_handle(self)
|
||||
fetch_opts.callbacks.payload = self._self_handle
|
||||
if callbacks is None:
|
||||
callbacks = RemoteCallbacks()
|
||||
|
||||
self._stored_exception = None
|
||||
callbacks._fill_fetch_options(fetch_opts)
|
||||
|
||||
try:
|
||||
with StrArray(refspecs) as arr:
|
||||
err = C.git_remote_fetch(self._remote, arr, fetch_opts, to_bytes(message))
|
||||
if self._stored_exception:
|
||||
raise self._stored_exception
|
||||
if callbacks._stored_exception:
|
||||
raise callbacks._stored_exception
|
||||
check_error(err)
|
||||
finally:
|
||||
self._self_handle = None
|
||||
callbacks._self_handle = None
|
||||
|
||||
return TransferProgress(C.git_remote_stats(self._remote))
|
||||
|
||||
@ -225,123 +409,33 @@ class Remote(object):
|
||||
|
||||
return strarray_to_strings(specs)
|
||||
|
||||
def push(self, specs):
|
||||
def push(self, specs, callbacks=None):
|
||||
"""Push the given refspec to the remote. Raises ``GitError`` on
|
||||
protocol error or unpack failure.
|
||||
|
||||
When the remote has a githook installed, that denies the reference
|
||||
this function will return successfully. Thus it is stronly recommended
|
||||
to install a callback, that implements
|
||||
:py:meth:`RemoteCallbacks.push_update_reference` and check the passed
|
||||
parameters for successfull operations.
|
||||
|
||||
:param [str] specs: push refspecs to use
|
||||
"""
|
||||
push_opts = ffi.new('git_push_options *')
|
||||
err = C.git_push_init_options(push_opts, C.GIT_PUSH_OPTIONS_VERSION)
|
||||
|
||||
if callbacks is None:
|
||||
callbacks = RemoteCallbacks()
|
||||
|
||||
callbacks._fill_push_options(push_opts)
|
||||
# Build custom callback structure
|
||||
push_opts.callbacks.sideband_progress = self._sideband_progress_cb
|
||||
push_opts.callbacks.transfer_progress = self._transfer_progress_cb
|
||||
push_opts.callbacks.update_tips = self._update_tips_cb
|
||||
push_opts.callbacks.credentials = self._credentials_cb
|
||||
push_opts.callbacks.push_update_reference = self._push_update_reference_cb
|
||||
# We need to make sure that this handle stays alive
|
||||
self._self_handle = ffi.new_handle(self)
|
||||
push_opts.callbacks.payload = self._self_handle
|
||||
|
||||
try:
|
||||
with StrArray(specs) as refspecs:
|
||||
err = C.git_remote_push(self._remote, refspecs, ffi.NULL)
|
||||
err = C.git_remote_push(self._remote, refspecs, push_opts)
|
||||
check_error(err)
|
||||
finally:
|
||||
self._self_handle = None
|
||||
|
||||
# These functions exist to be called by the git_remote as
|
||||
# callbacks. They proxy the call to whatever the user set
|
||||
|
||||
@ffi.callback('git_transfer_progress_cb')
|
||||
def _transfer_progress_cb(stats_ptr, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'transfer_progress') \
|
||||
or not self.transfer_progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
self.transfer_progress(TransferProgress(stats_ptr))
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('git_transport_message_cb')
|
||||
def _sideband_progress_cb(string, length, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'progress') or not self.progress:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = ffi.string(string, length).decode()
|
||||
self.progress(s)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*update_tips)(const char *refname, const git_oid *a,'
|
||||
'const git_oid *b, void *data)')
|
||||
def _update_tips_cb(refname, a, b, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'update_tips') or not self.update_tips:
|
||||
return 0
|
||||
|
||||
try:
|
||||
s = maybe_string(refname)
|
||||
a = Oid(raw=bytes(ffi.buffer(a)[:]))
|
||||
b = Oid(raw=bytes(ffi.buffer(b)[:]))
|
||||
|
||||
self.update_tips(s, a, b)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback("int (*push_update_reference)(const char *ref, const char *msg, void *data)")
|
||||
def _push_update_reference_cb(ref, msg, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'push_update_reference') or not self.push_update_reference:
|
||||
return 0
|
||||
|
||||
try:
|
||||
refname = ffi.string(ref)
|
||||
message = maybe_string(msg)
|
||||
self.push_update_reference(refname, message)
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
@ffi.callback('int (*credentials)(git_cred **cred, const char *url,'
|
||||
'const char *username_from_url, unsigned int allowed_types,'
|
||||
'void *data)')
|
||||
def _credentials_cb(cred_out, url, username, allowed, data):
|
||||
self = ffi.from_handle(data)
|
||||
|
||||
if not hasattr(self, 'credentials') or not self.credentials:
|
||||
return 0
|
||||
|
||||
try:
|
||||
ccred = get_credentials(self.credentials, url, username, allowed)
|
||||
cred_out[0] = ccred[0]
|
||||
|
||||
except Exception as e:
|
||||
self._stored_exception = e
|
||||
return C.GIT_EUSER
|
||||
|
||||
return 0
|
||||
|
||||
callbacks._self_handle = None
|
||||
|
||||
def get_credentials(fn, url, username, allowed):
|
||||
"""Call fn and return the credentials object"""
|
||||
@ -351,23 +445,24 @@ def get_credentials(fn, url, username, allowed):
|
||||
|
||||
creds = fn(url_str, username_str, allowed)
|
||||
|
||||
if not hasattr(creds, 'credential_type') \
|
||||
or not hasattr(creds, 'credential_tuple'):
|
||||
credential_type = getattr(creds, 'credential_type', None)
|
||||
credential_tuple = getattr(creds, 'credential_tuple', None)
|
||||
if not credential_type or not credential_tuple:
|
||||
raise TypeError("credential does not implement interface")
|
||||
|
||||
cred_type = creds.credential_type
|
||||
cred_type = credential_type
|
||||
|
||||
if not (allowed & cred_type):
|
||||
raise TypeError("invalid credential type")
|
||||
|
||||
ccred = ffi.new('git_cred **')
|
||||
if cred_type == C.GIT_CREDTYPE_USERPASS_PLAINTEXT:
|
||||
name, passwd = creds.credential_tuple
|
||||
name, passwd = credential_tuple
|
||||
err = C.git_cred_userpass_plaintext_new(ccred, to_bytes(name),
|
||||
to_bytes(passwd))
|
||||
|
||||
elif cred_type == C.GIT_CREDTYPE_SSH_KEY:
|
||||
name, pubkey, privkey, passphrase = creds.credential_tuple
|
||||
name, pubkey, privkey, passphrase = credential_tuple
|
||||
if pubkey is None and privkey is None:
|
||||
err = C.git_cred_ssh_key_from_agent(ccred, to_bytes(name))
|
||||
else:
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -32,17 +32,21 @@ from __future__ import absolute_import
|
||||
from string import hexdigits
|
||||
import sys, tarfile
|
||||
from time import time
|
||||
|
||||
if sys.version_info[0] < 3:
|
||||
from cStringIO import StringIO
|
||||
else:
|
||||
from io import BytesIO as StringIO
|
||||
|
||||
import six
|
||||
|
||||
# Import from pygit2
|
||||
from _pygit2 import Repository as _Repository
|
||||
from _pygit2 import Repository as _Repository, init_file_backend
|
||||
from _pygit2 import Oid, GIT_OID_HEXSZ, GIT_OID_MINPREFIXLEN
|
||||
from _pygit2 import GIT_CHECKOUT_SAFE, GIT_CHECKOUT_RECREATE_MISSING, GIT_DIFF_NORMAL
|
||||
from _pygit2 import GIT_FILEMODE_LINK
|
||||
from _pygit2 import Reference, Tree, Commit, Blob
|
||||
from _pygit2 import GIT_BRANCH_LOCAL, GIT_BRANCH_REMOTE, GIT_BRANCH_ALL
|
||||
from _pygit2 import Reference, Tree, Commit, Blob, Signature
|
||||
|
||||
from .config import Config
|
||||
from .errors import check_error
|
||||
@ -54,21 +58,11 @@ from .utils import to_bytes, is_string
|
||||
from .submodule import Submodule
|
||||
|
||||
|
||||
class Repository(_Repository):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Repository, self).__init__(*args, **kwargs)
|
||||
class BaseRepository(_Repository):
|
||||
def __init__(self, backend, *args, **kwargs):
|
||||
super(BaseRepository, self).__init__(backend, *args, **kwargs)
|
||||
self._common_init()
|
||||
|
||||
@classmethod
|
||||
def _from_c(cls, ptr, owned):
|
||||
cptr = ffi.new('git_repository **')
|
||||
cptr[0] = ptr
|
||||
repo = cls.__new__(cls)
|
||||
super(cls, repo)._from_c(bytes(ffi.buffer(cptr)[:]), owned)
|
||||
repo._common_init()
|
||||
return repo
|
||||
|
||||
def _common_init(self):
|
||||
self.remotes = RemoteCollection(self)
|
||||
|
||||
@ -275,11 +269,6 @@ class Repository(_Repository):
|
||||
oid = reference.resolve().target
|
||||
treeish = self[oid]
|
||||
self.checkout_tree(treeish, **kwargs)
|
||||
head = self.lookup_reference('HEAD')
|
||||
if head.type == C.GIT_REF_SYMBOLIC:
|
||||
from_ = self.head.shorthand
|
||||
else:
|
||||
from_ = head.target.hex
|
||||
|
||||
self.set_head(refname)
|
||||
|
||||
@ -318,8 +307,23 @@ class Repository(_Repository):
|
||||
|
||||
Keyword arguments:
|
||||
|
||||
a
|
||||
None, a str (that refers to an Object, see revparse_single()) or a
|
||||
Reference object.
|
||||
If None, b must be None, too. In this case the working directory is
|
||||
compared with the index. Otherwise the referred object is compared to
|
||||
'b'.
|
||||
|
||||
b
|
||||
None, a str (that refers to an Object, see revparse_single()) or a
|
||||
Reference object.
|
||||
If None, the working directory is compared to 'a'. (except
|
||||
'cached' is True, in which case the index is compared to 'a').
|
||||
Otherwise the referred object is compared to 'a'
|
||||
|
||||
cached
|
||||
use staged changes instead of workdir
|
||||
if 'b' is None, by default the working directory is compared to 'a'.
|
||||
If 'cached' is set to True, the index/staging area is used for comparing.
|
||||
|
||||
flag
|
||||
a GIT_DIFF_* constant
|
||||
@ -481,6 +485,7 @@ class Repository(_Repository):
|
||||
@staticmethod
|
||||
def _merge_options(favor):
|
||||
"""Return a 'git_merge_opts *'"""
|
||||
|
||||
def favor_to_enum(favor):
|
||||
if favor == 'normal':
|
||||
return C.GIT_MERGE_FILE_FAVOR_NORMAL
|
||||
@ -527,13 +532,13 @@ class Repository(_Repository):
|
||||
theirs._to_c() if theirs is not None else (ffi.NULL, ffi.NULL))
|
||||
|
||||
err = C.git_merge_file_from_index(
|
||||
cmergeresult, self._repo,
|
||||
cancestor, cours, ctheirs,
|
||||
ffi.NULL);
|
||||
cmergeresult, self._repo,
|
||||
cancestor, cours, ctheirs,
|
||||
ffi.NULL);
|
||||
check_error(err)
|
||||
|
||||
ret = ffi.string(cmergeresult.ptr,
|
||||
cmergeresult.len).decode('utf-8')
|
||||
cmergeresult.len).decode('utf-8')
|
||||
C.git_merge_file_result_free(cmergeresult)
|
||||
|
||||
return ret
|
||||
@ -637,6 +642,196 @@ class Repository(_Repository):
|
||||
|
||||
return Index.from_c(self, cindex)
|
||||
|
||||
#
|
||||
# Describe
|
||||
#
|
||||
def describe(self, committish=None, max_candidates_tags=None,
|
||||
describe_strategy=None, pattern=None,
|
||||
only_follow_first_parent=None,
|
||||
show_commit_oid_as_fallback=None, abbreviated_size=None,
|
||||
always_use_long_format=None, dirty_suffix=None):
|
||||
"""Describe a commit-ish or the current working tree.
|
||||
|
||||
:param committish: Commit-ish object or object name to describe, or
|
||||
`None` to describe the current working tree.
|
||||
:type committish: `str`, :class:`~.Reference`, or :class:`~.Commit`
|
||||
|
||||
:param int max_candidates_tags: The number of candidate tags to
|
||||
consider. Increasing above 10 will take slightly longer but may
|
||||
produce a more accurate result. A value of 0 will cause only exact
|
||||
matches to be output.
|
||||
:param int describe_strategy: A GIT_DESCRIBE_* constant.
|
||||
:param str pattern: Only consider tags matching the given `glob(7)`
|
||||
pattern, excluding the "refs/tags/" prefix.
|
||||
:param bool only_follow_first_parent: Follow only the first parent
|
||||
commit upon seeing a merge commit.
|
||||
:param bool show_commit_oid_as_fallback: Show uniquely abbreviated
|
||||
commit object as fallback.
|
||||
:param int abbreviated_size: The minimum number of hexadecimal digits
|
||||
to show for abbreviated object names. A value of 0 will suppress
|
||||
long format, only showing the closest tag.
|
||||
:param bool always_use_long_format: Always output the long format (the
|
||||
nearest tag, the number of commits, and the abbrevated commit name)
|
||||
even when the committish matches a tag.
|
||||
:param str dirty_suffix: A string to append if the working tree is
|
||||
dirty.
|
||||
|
||||
:returns: The description.
|
||||
:rtype: `str`
|
||||
|
||||
Example::
|
||||
|
||||
repo.describe(pattern='public/*', dirty_suffix='-dirty')
|
||||
"""
|
||||
|
||||
options = ffi.new('git_describe_options *')
|
||||
C.git_describe_init_options(options, C.GIT_DESCRIBE_OPTIONS_VERSION)
|
||||
|
||||
if max_candidates_tags is not None:
|
||||
options.max_candidates_tags = max_candidates_tags
|
||||
if describe_strategy is not None:
|
||||
options.describe_strategy = describe_strategy
|
||||
if pattern:
|
||||
# The returned pointer object has ownership on the allocated
|
||||
# memory. Make sure it is kept alive until git_describe_commit() or
|
||||
# git_describe_workdir() are called below.
|
||||
pattern_char = ffi.new('char[]', to_bytes(pattern))
|
||||
options.pattern = pattern_char
|
||||
if only_follow_first_parent is not None:
|
||||
options.only_follow_first_parent = only_follow_first_parent
|
||||
if show_commit_oid_as_fallback is not None:
|
||||
options.show_commit_oid_as_fallback = show_commit_oid_as_fallback
|
||||
|
||||
result = ffi.new('git_describe_result **')
|
||||
if committish:
|
||||
if is_string(committish):
|
||||
committish = self.revparse_single(committish)
|
||||
|
||||
commit = committish.peel(Commit)
|
||||
|
||||
cptr = ffi.new('git_object **')
|
||||
ffi.buffer(cptr)[:] = commit._pointer[:]
|
||||
|
||||
err = C.git_describe_commit(result, cptr[0], options)
|
||||
else:
|
||||
err = C.git_describe_workdir(result, self._repo, options)
|
||||
check_error(err)
|
||||
|
||||
try:
|
||||
format_options = ffi.new('git_describe_format_options *')
|
||||
C.git_describe_init_format_options(format_options, C.GIT_DESCRIBE_FORMAT_OPTIONS_VERSION)
|
||||
|
||||
if abbreviated_size is not None:
|
||||
format_options.abbreviated_size = abbreviated_size
|
||||
if always_use_long_format is not None:
|
||||
format_options.always_use_long_format = always_use_long_format
|
||||
dirty_ptr = None
|
||||
if dirty_suffix:
|
||||
dirty_ptr = ffi.new('char[]', to_bytes(dirty_suffix))
|
||||
format_options.dirty_suffix = dirty_ptr
|
||||
|
||||
buf = ffi.new('git_buf *', (ffi.NULL, 0))
|
||||
|
||||
err = C.git_describe_format(buf, result[0], format_options)
|
||||
check_error(err)
|
||||
|
||||
try:
|
||||
return ffi.string(buf.ptr).decode('utf-8')
|
||||
finally:
|
||||
C.git_buf_free(buf)
|
||||
finally:
|
||||
C.git_describe_result_free(result[0])
|
||||
|
||||
#
|
||||
# Stash
|
||||
#
|
||||
def stash(self, stasher, message=None, keep_index=False,
|
||||
include_untracked=False, include_ignored=False):
|
||||
"""Save changes to the working directory to the stash.
|
||||
|
||||
:param Signature stasher: The identity of the person doing the stashing.
|
||||
:param str message: An optional description of stashed state.
|
||||
:param bool keep_index: Leave changes already added to the index
|
||||
in the working directory.
|
||||
:param bool include_untracked: Also stash untracked files.
|
||||
:param bool include_ignored: Also stash ignored files.
|
||||
|
||||
:returns: The Oid of the stash merge commit.
|
||||
:rtype: Oid
|
||||
|
||||
Example::
|
||||
|
||||
>>> repo = pygit2.Repsitory('.')
|
||||
>>> repo.stash(repo.default_signature(), 'WIP: stashing')
|
||||
"""
|
||||
|
||||
if message is not None:
|
||||
stash_msg = ffi.new('char[]', to_bytes(message)) if message else ffi.NULL
|
||||
else:
|
||||
stash_msg = ffi.NULL
|
||||
|
||||
flags = 0
|
||||
flags |= keep_index * C.GIT_STASH_KEEP_INDEX
|
||||
flags |= include_untracked * C.GIT_STASH_INCLUDE_UNTRACKED
|
||||
flags |= include_ignored * C.GIT_STASH_INCLUDE_IGNORED
|
||||
|
||||
stasher_cptr = ffi.new('git_signature **')
|
||||
ffi.buffer(stasher_cptr)[:] = stasher._pointer[:]
|
||||
|
||||
coid = ffi.new('git_oid *')
|
||||
err = C.git_stash_save(coid, self._repo, stasher_cptr[0], stash_msg, flags)
|
||||
check_error(err)
|
||||
|
||||
return Oid(raw=bytes(ffi.buffer(coid)[:]))
|
||||
|
||||
@staticmethod
|
||||
def _stash_args_to_options(reinstate_index=False, **kwargs):
|
||||
stash_opts = ffi.new('git_stash_apply_options *')
|
||||
check_error(C.git_stash_apply_init_options(stash_opts, 1))
|
||||
|
||||
flags = reinstate_index * C.GIT_STASH_APPLY_REINSTATE_INDEX
|
||||
stash_opts.flags = flags
|
||||
|
||||
copts, refs = Repository._checkout_args_to_options(**kwargs)
|
||||
stash_opts.checkout_options = copts[0]
|
||||
|
||||
return stash_opts
|
||||
|
||||
def stash_apply(self, index=0, **kwargs):
|
||||
"""Apply a stashed state in the stash list to the working directory.
|
||||
|
||||
:param int index: The position within the stash list of the stash to apply.
|
||||
0 is the most recent stash.
|
||||
:param bool reinstate_index: Try to reinstate stashed changes to the index.
|
||||
|
||||
The checkout options may be customized using the same arguments taken by
|
||||
Repository.checkout().
|
||||
|
||||
Example::
|
||||
|
||||
>>> repo = pygit2.Repsitory('.')
|
||||
>>> repo.stash(repo.default_signature(), 'WIP: stashing')
|
||||
>>> repo.stash_apply(strategy=GIT_CHECKOUT_ALLOW_CONFLICTS)
|
||||
"""
|
||||
stash_opts = Repository._stash_args_to_options(**kwargs)
|
||||
check_error(C.git_stash_apply(self._repo, index, stash_opts))
|
||||
|
||||
def stash_drop(self, index=0):
|
||||
"""Remove a stashed state from the stash list.
|
||||
|
||||
:param int index: The position within the stash list of the stash to remove.
|
||||
0 is the most recent stash.
|
||||
"""
|
||||
check_error(C.git_stash_drop(self._repo, index))
|
||||
|
||||
def stash_pop(self, index=0, **kwargs):
|
||||
"""Apply a stashed state and remove it from the stash list.
|
||||
|
||||
For arguments, see Repository.stash_apply().
|
||||
"""
|
||||
stash_opts = Repository._stash_args_to_options(**kwargs)
|
||||
check_error(C.git_stash_pop(self._repo, index, stash_opts))
|
||||
|
||||
#
|
||||
# Utility for writing a tree into an archive
|
||||
#
|
||||
@ -665,7 +860,7 @@ class Repository(_Repository):
|
||||
>>> import tarfile, pygit2
|
||||
>>>> with tarfile.open('foo.tar', 'w') as archive:
|
||||
>>>> repo = pygit2.Repsitory('.')
|
||||
>>>> repo.write_archive(archive, repo.head.target)
|
||||
>>>> repo.write_archive(repo.head.target, archive)
|
||||
"""
|
||||
|
||||
# Try to get a tree form whatever we got
|
||||
@ -697,11 +892,11 @@ class Repository(_Repository):
|
||||
info = tarfile.TarInfo(prefix + entry.path)
|
||||
info.size = len(content)
|
||||
info.mtime = timestamp
|
||||
info.uname = info.gname = 'root' # just because git does this
|
||||
info.uname = info.gname = 'root' # just because git does this
|
||||
if entry.mode == GIT_FILEMODE_LINK:
|
||||
info.type = archive.SYMTYPE
|
||||
info.linkname = content
|
||||
info.mode = 0o777 # symlinks get placeholder
|
||||
info.type = tarfile.SYMTYPE
|
||||
info.linkname = content.decode("utf-8")
|
||||
info.mode = 0o777 # symlinks get placeholder
|
||||
info.size = 0
|
||||
archive.addfile(info)
|
||||
else:
|
||||
@ -805,3 +1000,130 @@ class Repository(_Repository):
|
||||
|
||||
err = C.git_repository_set_ident(self._repo, to_bytes(name), to_bytes(email))
|
||||
check_error(err)
|
||||
|
||||
def revert_commit(self, revert_commit, our_commit, mainline=0):
|
||||
"""Reverts the given Commit against the given "our" Commit,
|
||||
producing an Index that reflects the result of the revert.
|
||||
|
||||
Arguments
|
||||
|
||||
revert_commit
|
||||
The Commit to revert
|
||||
our_commit
|
||||
The Commit to revert against (eg, HEAD)
|
||||
mainline
|
||||
The parent of the revert Commit, if it is a merge (i.e. 1, 2)
|
||||
|
||||
Returns an Index with the result of the revert.
|
||||
"""
|
||||
cindex = ffi.new('git_index **')
|
||||
revert_commit_ptr = ffi.new('git_commit **')
|
||||
our_commit_ptr = ffi.new('git_commit **')
|
||||
|
||||
ffi.buffer(revert_commit_ptr)[:] = revert_commit._pointer[:]
|
||||
ffi.buffer(our_commit_ptr)[:] = our_commit._pointer[:]
|
||||
|
||||
opts = ffi.new('git_merge_options *')
|
||||
err = C.git_merge_init_options(opts, C.GIT_MERGE_OPTIONS_VERSION)
|
||||
check_error(err)
|
||||
|
||||
err = C.git_revert_commit(
|
||||
cindex, self._repo, revert_commit_ptr[0], our_commit_ptr[0], mainline, opts
|
||||
)
|
||||
check_error(err)
|
||||
|
||||
return Index.from_c(self, cindex)
|
||||
|
||||
|
||||
class Branches(object):
|
||||
def __init__(self, repository, flag=GIT_BRANCH_ALL):
|
||||
self._repository = repository
|
||||
self._flag = flag
|
||||
|
||||
if flag == GIT_BRANCH_ALL:
|
||||
self.local = Branches(repository, flag=GIT_BRANCH_LOCAL)
|
||||
self.remote = Branches(repository, flag=GIT_BRANCH_REMOTE)
|
||||
|
||||
def __getitem__(self, name):
|
||||
branch = None
|
||||
if self._flag & GIT_BRANCH_LOCAL:
|
||||
branch = self._repository.lookup_branch(name, GIT_BRANCH_LOCAL)
|
||||
|
||||
if branch is None and self._flag & GIT_BRANCH_REMOTE:
|
||||
branch = self._repository.lookup_branch(name, GIT_BRANCH_REMOTE)
|
||||
|
||||
if branch is None:
|
||||
raise KeyError('Branch not found: {}'.format(name))
|
||||
|
||||
return branch
|
||||
|
||||
def get(self, key):
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def __iter__(self):
|
||||
for branch_name in self._repository.listall_branches(self._flag):
|
||||
yield branch_name
|
||||
|
||||
def create(self, name, commit, force=False):
|
||||
return self._repository.create_branch(name, commit, force)
|
||||
|
||||
def delete(self, name):
|
||||
self[name].delete()
|
||||
|
||||
def __contains__(self, name):
|
||||
return self.get(name) is not None
|
||||
|
||||
|
||||
class References(object):
|
||||
def __init__(self, repository):
|
||||
self._repository = repository
|
||||
|
||||
def __getitem__(self, name):
|
||||
return self._repository.lookup_reference(name)
|
||||
|
||||
def get(self, key):
|
||||
try:
|
||||
return self[key]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
def __iter__(self):
|
||||
for ref_name in self._repository.listall_references():
|
||||
yield ref_name
|
||||
|
||||
def create(self, name, target, force=False):
|
||||
return self._repository.create_reference(name, target, force)
|
||||
|
||||
def delete(self, name):
|
||||
self[name].delete()
|
||||
|
||||
def __contains__(self, name):
|
||||
return self.get(name) is not None
|
||||
|
||||
@property
|
||||
def objects(self):
|
||||
return self._repository.listall_reference_objects()
|
||||
|
||||
|
||||
class Repository(BaseRepository):
|
||||
def __init__(self, path, *args, **kwargs):
|
||||
if not isinstance(path, six.string_types):
|
||||
path = path.decode('utf-8')
|
||||
|
||||
path_backend = init_file_backend(path)
|
||||
super(Repository, self).__init__(backend=path_backend, *args, **kwargs)
|
||||
|
||||
self.branches = Branches(self)
|
||||
self.references = References(self)
|
||||
|
||||
@classmethod
|
||||
def _from_c(cls, ptr, owned):
|
||||
cptr = ffi.new('git_repository **')
|
||||
cptr[0] = ptr
|
||||
repo = cls.__new__(cls)
|
||||
super(cls, repo)._from_c(bytes(ffi.buffer(cptr)[:]), owned)
|
||||
repo._common_init()
|
||||
return repo
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -28,6 +28,11 @@
|
||||
from _pygit2 import option
|
||||
from _pygit2 import GIT_OPT_GET_SEARCH_PATH, GIT_OPT_SET_SEARCH_PATH
|
||||
from _pygit2 import GIT_OPT_GET_MWINDOW_SIZE, GIT_OPT_SET_MWINDOW_SIZE
|
||||
from _pygit2 import GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, GIT_OPT_SET_MWINDOW_MAPPED_LIMIT
|
||||
from _pygit2 import GIT_OPT_SET_CACHE_OBJECT_LIMIT
|
||||
from _pygit2 import GIT_OPT_GET_CACHED_MEMORY
|
||||
from _pygit2 import GIT_OPT_ENABLE_CACHING
|
||||
from _pygit2 import GIT_OPT_SET_CACHE_MAX_SIZE
|
||||
|
||||
|
||||
class SearchPathList(object):
|
||||
@ -64,3 +69,36 @@ class Settings(object):
|
||||
@mwindow_size.setter
|
||||
def mwindow_size(self, value):
|
||||
option(GIT_OPT_SET_MWINDOW_SIZE, value)
|
||||
|
||||
@property
|
||||
def mwindow_mapped_limit(self):
|
||||
"""Mwindow mapped limit"""
|
||||
return option(GIT_OPT_GET_MWINDOW_MAPPED_LIMIT)
|
||||
|
||||
@mwindow_mapped_limit.setter
|
||||
def mwindow_mapped_limit(self, value):
|
||||
"""Mwindow mapped limit"""
|
||||
return option(GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, value)
|
||||
|
||||
@property
|
||||
def cached_memory(self):
|
||||
"""Maximum mmap window size"""
|
||||
return option(GIT_OPT_GET_CACHED_MEMORY)
|
||||
|
||||
def enable_caching(self, value=True):
|
||||
return option(GIT_OPT_ENABLE_CACHING, value)
|
||||
|
||||
def cache_max_size(self, value):
|
||||
return option(GIT_OPT_SET_CACHE_MAX_SIZE, value)
|
||||
|
||||
def cache_object_limit(self, object_type, value):
|
||||
"""Set the maximum data size for the given type of object to be
|
||||
considered eligible for caching in memory.
|
||||
|
||||
Setting to value to zero means that that type of object will not
|
||||
be cached. Defaults to 0 for GIT_OBJ_BLOB (i.e. won't cache
|
||||
blobs) and 4k for GIT_OBJ_COMMIT, GIT_OBJ_TREE, and GIT_OBJ_TAG.
|
||||
"""
|
||||
return option(GIT_OPT_SET_CACHE_OBJECT_LIMIT, object_type, value)
|
||||
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
129
setup.py
129
setup.py
@ -1,7 +1,7 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# coding: UTF-8
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -45,22 +45,26 @@ from subprocess import Popen, PIPE
|
||||
import sys
|
||||
import unittest
|
||||
|
||||
# Get cffi major version
|
||||
try:
|
||||
import cffi
|
||||
except ImportError:
|
||||
cffi_major_version = None
|
||||
else:
|
||||
cffi_major_version = cffi.__version_info__[0]
|
||||
|
||||
# Import stuff from pygit2/_utils.py without loading the whole pygit2 package
|
||||
sys.path.insert(0, 'pygit2')
|
||||
from _utils import __version__, get_libgit2_paths, get_ffi
|
||||
from _build import __version__, get_libgit2_paths
|
||||
if cffi_major_version == 0:
|
||||
from _run import ffi, preamble, C_KEYWORDS
|
||||
ffi.verify(preamble, **C_KEYWORDS)
|
||||
del sys.path[0]
|
||||
|
||||
# Python 2 support
|
||||
# See https://github.com/libgit2/pygit2/pull/180 for a discussion about this.
|
||||
if sys.version_info[0] == 2:
|
||||
u = lambda s: unicode(s, 'utf-8')
|
||||
else:
|
||||
u = str
|
||||
|
||||
|
||||
libgit2_bin, libgit2_include, libgit2_lib = get_libgit2_paths()
|
||||
|
||||
pygit2_exts = [os.path.join('src', name) for name in listdir('src')
|
||||
pygit2_exts = [os.path.join('src', name) for name in sorted(listdir('src'))
|
||||
if name.endswith('.c')]
|
||||
|
||||
|
||||
@ -95,19 +99,43 @@ class TestCommand(Command):
|
||||
unittest.main(None, defaultTest='test.test_suite', argv=test_argv)
|
||||
|
||||
|
||||
class CFFIBuild(build):
|
||||
"""Hack to combat the chicken and egg problem that we need cffi
|
||||
to add cffi as an extension.
|
||||
"""
|
||||
def finalize_options(self):
|
||||
ffi, C = get_ffi()
|
||||
self.distribution.ext_modules.append(ffi.verifier.get_extension())
|
||||
build.finalize_options(self)
|
||||
class sdist_files_from_git(sdist):
|
||||
def get_file_list(self):
|
||||
popen = Popen(['git', 'ls-files'], stdout=PIPE, stderr=PIPE,
|
||||
universal_newlines=True)
|
||||
stdoutdata, stderrdata = popen.communicate()
|
||||
if popen.returncode != 0:
|
||||
print(stderrdata)
|
||||
sys.exit()
|
||||
|
||||
for line in stdoutdata.splitlines():
|
||||
# Skip hidden files at the root
|
||||
if line[0] == '.':
|
||||
continue
|
||||
self.filelist.append(line)
|
||||
|
||||
# Ok
|
||||
self.filelist.sort()
|
||||
self.filelist.remove_duplicates()
|
||||
self.write_manifest()
|
||||
|
||||
|
||||
class BuildWithDLLs(CFFIBuild):
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Version Control"]
|
||||
|
||||
# On Windows, we install the git2.dll too.
|
||||
with codecs.open('README.rst', 'r', 'utf-8') as readme:
|
||||
long_description = readme.read()
|
||||
|
||||
cmdclass = {
|
||||
'test': TestCommand,
|
||||
'sdist': sdist_files_from_git,
|
||||
}
|
||||
|
||||
|
||||
# On Windows, we install the git2.dll too.
|
||||
class BuildWithDLLs(build):
|
||||
def _get_dlls(self):
|
||||
# return a list of (FQ-in-name, relative-out-name) tuples.
|
||||
ret = []
|
||||
@ -133,45 +161,27 @@ class BuildWithDLLs(CFFIBuild):
|
||||
|
||||
def run(self):
|
||||
build.run(self)
|
||||
# On Windows we package up the dlls with the plugin.
|
||||
for s, d in self._get_dlls():
|
||||
self.copy_file(s, d)
|
||||
|
||||
# On Windows we package up the dlls with the plugin.
|
||||
if os.name == 'nt':
|
||||
cmdclass['build'] = BuildWithDLLs
|
||||
|
||||
class sdist_files_from_git(sdist):
|
||||
def get_file_list(self):
|
||||
popen = Popen(['git', 'ls-files'], stdout=PIPE, stderr=PIPE)
|
||||
stdoutdata, stderrdata = popen.communicate()
|
||||
if popen.returncode != 0:
|
||||
print(stderrdata)
|
||||
sys.exit()
|
||||
extra_args = {
|
||||
'ext_modules': [
|
||||
Extension('_pygit2', pygit2_exts, libraries=['git2'],
|
||||
include_dirs=[libgit2_include],
|
||||
library_dirs=[libgit2_lib]),
|
||||
# FFI is added in the build step
|
||||
],
|
||||
}
|
||||
|
||||
for line in stdoutdata.splitlines():
|
||||
# Skip hidden files at the root
|
||||
if line[0] == '.':
|
||||
continue
|
||||
self.filelist.append(line)
|
||||
if cffi_major_version == 0:
|
||||
extra_args['ext_modules'].append(ffi.verifier.get_extension())
|
||||
else:
|
||||
extra_args['cffi_modules'] = ['pygit2/_run.py:ffi']
|
||||
|
||||
# Ok
|
||||
self.filelist.sort()
|
||||
self.filelist.remove_duplicates()
|
||||
self.write_manifest()
|
||||
|
||||
classifiers = [
|
||||
"Development Status :: 3 - Alpha",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Version Control"]
|
||||
|
||||
|
||||
with codecs.open('README.rst', 'r', 'utf-8') as readme:
|
||||
long_description = readme.read()
|
||||
|
||||
|
||||
cmdclass = {
|
||||
'build': BuildWithDLLs if os.name == 'nt' else CFFIBuild,
|
||||
'test': TestCommand,
|
||||
'sdist': sdist_files_from_git,
|
||||
}
|
||||
|
||||
setup(name='pygit2',
|
||||
description='Python bindings for libgit2.',
|
||||
@ -180,18 +190,13 @@ setup(name='pygit2',
|
||||
url='http://github.com/libgit2/pygit2',
|
||||
classifiers=classifiers,
|
||||
license='GPLv2 with linking exception',
|
||||
maintainer=u('J. David Ibáñez'),
|
||||
maintainer=u'J. David Ibáñez',
|
||||
maintainer_email='jdavid.ibp@gmail.com',
|
||||
long_description=long_description,
|
||||
packages=['pygit2'],
|
||||
package_data={'pygit2': ['decl.h']},
|
||||
setup_requires=['cffi'],
|
||||
install_requires=['cffi'],
|
||||
install_requires=['cffi', 'six'],
|
||||
zip_safe=False,
|
||||
ext_modules=[
|
||||
Extension('_pygit2', pygit2_exts, libraries=['git2'],
|
||||
include_dirs=[libgit2_include],
|
||||
library_dirs=[libgit2_lib]),
|
||||
# FFI is added in the build step
|
||||
],
|
||||
cmdclass=cmdclass)
|
||||
cmdclass=cmdclass,
|
||||
**extra_args)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -133,7 +133,7 @@ PyDoc_STRVAR(Blob_size__doc__, "Size.");
|
||||
PyObject *
|
||||
Blob_size__get__(Blob *self)
|
||||
{
|
||||
return PyLong_FromLongLong(git_blob_rawsize(self->blob));
|
||||
return PyInt_FromLongLong(git_blob_rawsize(self->blob));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
25
src/branch.c
25
src/branch.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -81,6 +81,28 @@ Branch_is_head(Branch *self)
|
||||
return Error_set(err);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Branch_is_checked_out__doc__,
|
||||
"is_checked_out()\n"
|
||||
"\n"
|
||||
"True if branch is checked out by any repo connected to the current one, "
|
||||
" False otherwise.");
|
||||
|
||||
PyObject *
|
||||
Branch_is_checked_out(Branch *self)
|
||||
{
|
||||
int err;
|
||||
|
||||
CHECK_REFERENCE(self);
|
||||
|
||||
err = git_branch_is_checked_out(self->reference);
|
||||
if (err == 1)
|
||||
Py_RETURN_TRUE;
|
||||
else if (err == 0)
|
||||
Py_RETURN_FALSE;
|
||||
else
|
||||
return Error_set(err);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Branch_rename__doc__,
|
||||
"rename(name, force=False)\n"
|
||||
@ -234,6 +256,7 @@ Branch_upstream_name__get__(Branch *self)
|
||||
PyMethodDef Branch_methods[] = {
|
||||
METHOD(Branch, delete, METH_NOARGS),
|
||||
METHOD(Branch, is_head, METH_NOARGS),
|
||||
METHOD(Branch, is_checked_out, METH_NOARGS),
|
||||
METHOD(Branch, rename, METH_VARARGS),
|
||||
{NULL}
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -34,6 +34,7 @@
|
||||
|
||||
PyObject* Branch_delete(Branch *self, PyObject *args);
|
||||
PyObject* Branch_is_head(Branch *self);
|
||||
PyObject* Branch_is_checked_out(Branch *self);
|
||||
PyObject* Branch_move(Branch *self, PyObject *args);
|
||||
|
||||
PyObject* wrap_branch(git_reference *c_reference, Repository *repo);
|
||||
|
14
src/commit.c
14
src/commit.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -35,6 +35,7 @@
|
||||
#include "oid.h"
|
||||
|
||||
extern PyTypeObject TreeType;
|
||||
extern PyObject *GitError;
|
||||
|
||||
|
||||
PyDoc_STRVAR(Commit_message_encoding__doc__, "Message encoding.");
|
||||
@ -79,7 +80,7 @@ PyDoc_STRVAR(Commit_commit_time__doc__, "Commit time.");
|
||||
PyObject *
|
||||
Commit_commit_time__get__(Commit *commit)
|
||||
{
|
||||
return PyLong_FromLongLong(git_commit_time(commit->commit));
|
||||
return PyInt_FromLongLong(git_commit_time(commit->commit));
|
||||
}
|
||||
|
||||
|
||||
@ -88,7 +89,7 @@ PyDoc_STRVAR(Commit_commit_time_offset__doc__, "Commit time offset.");
|
||||
PyObject *
|
||||
Commit_commit_time_offset__get__(Commit *commit)
|
||||
{
|
||||
return PyLong_FromLong(git_commit_time_offset(commit->commit));
|
||||
return PyInt_FromLong(git_commit_time_offset(commit->commit));
|
||||
}
|
||||
|
||||
|
||||
@ -131,8 +132,11 @@ Commit_tree__get__(Commit *commit)
|
||||
int err;
|
||||
|
||||
err = git_commit_tree(&tree, commit->commit);
|
||||
if (err == GIT_ENOTFOUND)
|
||||
Py_RETURN_NONE;
|
||||
if (err == GIT_ENOTFOUND) {
|
||||
char tree_id[GIT_OID_HEXSZ + 1] = { 0 };
|
||||
git_oid_fmt(tree_id, git_commit_tree_id(commit->commit));
|
||||
return PyErr_Format(GitError, "Unable to read tree %s", tree_id);
|
||||
}
|
||||
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
17
src/diff.c
17
src/diff.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -482,7 +482,8 @@ Diff_len(Diff *self)
|
||||
return (Py_ssize_t)git_diff_num_deltas(self->diff);
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Diff_patch__doc__, "Patch diff string.");
|
||||
PyDoc_STRVAR(Diff_patch__doc__,
|
||||
"Patch diff string. Can be None in some cases, such as empty commits.");
|
||||
|
||||
PyObject *
|
||||
Diff_patch__get__(Diff *self)
|
||||
@ -586,7 +587,7 @@ PyDoc_STRVAR(DiffStats_insertions__doc__, "Total number of insertions");
|
||||
PyObject *
|
||||
DiffStats_insertions__get__(DiffStats *self)
|
||||
{
|
||||
return PyLong_FromSize_t(git_diff_stats_insertions(self->stats));
|
||||
return PyInt_FromSize_t(git_diff_stats_insertions(self->stats));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(DiffStats_deletions__doc__, "Total number of deletions");
|
||||
@ -594,7 +595,7 @@ PyDoc_STRVAR(DiffStats_deletions__doc__, "Total number of deletions");
|
||||
PyObject *
|
||||
DiffStats_deletions__get__(DiffStats *self)
|
||||
{
|
||||
return PyLong_FromSize_t(git_diff_stats_deletions(self->stats));
|
||||
return PyInt_FromSize_t(git_diff_stats_deletions(self->stats));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(DiffStats_files_changed__doc__, "Total number of files changed");
|
||||
@ -602,7 +603,7 @@ PyDoc_STRVAR(DiffStats_files_changed__doc__, "Total number of files changed");
|
||||
PyObject *
|
||||
DiffStats_files_changed__get__(DiffStats *self)
|
||||
{
|
||||
return PyLong_FromSize_t(git_diff_stats_files_changed(self->stats));
|
||||
return PyInt_FromSize_t(git_diff_stats_files_changed(self->stats));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(DiffStats_format__doc__,
|
||||
@ -804,10 +805,10 @@ Diff_getitem(Diff *self, PyObject *value)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (!PyLong_Check(value))
|
||||
return NULL;
|
||||
if (!PyInt_Check(value))
|
||||
return NULL; /* FIXME Raise error */
|
||||
|
||||
i = PyLong_AsUnsignedLong(value);
|
||||
i = PyInt_AsSize_t(value);
|
||||
return diff_get_patch_byindex(self->diff, i);
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -126,3 +126,10 @@ Error_set_oid(int err, const git_oid *oid, size_t len)
|
||||
hex[len] = '\0';
|
||||
return Error_set_str(err, hex);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
Error_type_error(const char *format, PyObject *value)
|
||||
{
|
||||
PyErr_Format(PyExc_TypeError, format, Py_TYPE(value)->tp_name);
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -37,5 +37,6 @@ PyObject* Error_set(int err);
|
||||
PyObject* Error_set_exc(PyObject* exception);
|
||||
PyObject* Error_set_str(int err, const char *str);
|
||||
PyObject* Error_set_oid(int err, const git_oid *oid, size_t len);
|
||||
PyObject* Error_type_error(const char *format, PyObject *value);
|
||||
|
||||
#endif
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
13
src/object.c
13
src/object.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -97,7 +97,7 @@ PyDoc_STRVAR(Object_type__doc__,
|
||||
PyObject *
|
||||
Object_type__get__(Object *self)
|
||||
{
|
||||
return PyLong_FromLong(git_object_type(self->obj));
|
||||
return PyInt_FromLong(git_object_type(self->obj));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Object__pointer__doc__, "Get the object's pointer. For internal use only.");
|
||||
@ -143,14 +143,15 @@ PyDoc_STRVAR(Object_peel__doc__,
|
||||
PyObject *
|
||||
Object_peel(Object *self, PyObject *py_type)
|
||||
{
|
||||
int type = -1, err;
|
||||
int err;
|
||||
git_otype otype;
|
||||
git_object *peeled;
|
||||
|
||||
type = py_object_to_object_type(py_type);
|
||||
if (type == -1)
|
||||
otype = py_object_to_otype(py_type);
|
||||
if (otype == GIT_OBJ_BAD)
|
||||
return NULL;
|
||||
|
||||
err = git_object_peel(&peeled, self->obj, (git_otype)type);
|
||||
err = git_object_peel(&peeled, self->obj, otype);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -209,8 +209,10 @@ Oid_init(Oid *self, PyObject *args, PyObject *kw)
|
||||
Py_hash_t
|
||||
Oid_hash(PyObject *oid)
|
||||
{
|
||||
/* TODO Randomize (use _Py_HashSecret) to avoid collission DoS attacks? */
|
||||
return *(Py_hash_t*) ((Oid*)oid)->oid.id;
|
||||
PyObject *py_oid = git_oid_to_py_str(&((Oid *)oid)->oid);
|
||||
Py_hash_t ret = PyObject_Hash(py_oid);
|
||||
Py_DECREF(py_oid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
182
src/options.c
182
src/options.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -65,10 +65,11 @@ option(PyObject *self, PyObject *args)
|
||||
if (!py_option)
|
||||
return NULL;
|
||||
|
||||
if (!PyLong_Check(py_option))
|
||||
goto on_non_integer;
|
||||
if (!PyInt_Check(py_option))
|
||||
return Error_type_error(
|
||||
"option should be an integer, got %.200s", py_option);
|
||||
|
||||
option = PyLong_AsLong(py_option);
|
||||
option = PyInt_AsLong(py_option);
|
||||
|
||||
switch (option) {
|
||||
case GIT_OPT_GET_SEARCH_PATH:
|
||||
@ -79,11 +80,11 @@ option(PyObject *self, PyObject *args)
|
||||
if (!py_level)
|
||||
return NULL;
|
||||
|
||||
if (!PyLong_Check(py_level))
|
||||
goto on_non_integer;
|
||||
if (!PyInt_Check(py_level))
|
||||
return Error_type_error(
|
||||
"level should be an integer, got %.200s", py_level);
|
||||
|
||||
return get_search_path(PyLong_AsLong(py_level));
|
||||
break;
|
||||
return get_search_path(PyInt_AsLong(py_level));
|
||||
}
|
||||
|
||||
case GIT_OPT_SET_SEARCH_PATH:
|
||||
@ -100,23 +101,22 @@ option(PyObject *self, PyObject *args)
|
||||
if (!py_path)
|
||||
return NULL;
|
||||
|
||||
if (!PyLong_Check(py_level))
|
||||
goto on_non_integer;
|
||||
if (!PyInt_Check(py_level))
|
||||
return Error_type_error(
|
||||
"level should be an integer, got %.200s", py_level);
|
||||
|
||||
path = py_str_borrow_c_str(&tpath, py_path, NULL);
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
err = git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, PyLong_AsLong(py_level), path);
|
||||
err = git_libgit2_opts(
|
||||
GIT_OPT_SET_SEARCH_PATH, PyInt_AsLong(py_level), path);
|
||||
Py_DECREF(tpath);
|
||||
|
||||
if (err < 0) {
|
||||
Error_set(err);
|
||||
return NULL;
|
||||
}
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
case GIT_OPT_GET_MWINDOW_SIZE:
|
||||
@ -124,14 +124,10 @@ option(PyObject *self, PyObject *args)
|
||||
size_t size;
|
||||
|
||||
error = git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &size);
|
||||
if (error < 0) {
|
||||
Error_set(error);
|
||||
return NULL;
|
||||
}
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
return PyLong_FromSize_t(size);
|
||||
|
||||
break;
|
||||
return PyInt_FromSize_t(size);
|
||||
}
|
||||
|
||||
case GIT_OPT_SET_MWINDOW_SIZE:
|
||||
@ -143,25 +139,141 @@ option(PyObject *self, PyObject *args)
|
||||
if (!py_size)
|
||||
return NULL;
|
||||
|
||||
if (!PyLong_Check(py_size))
|
||||
goto on_non_integer;
|
||||
if (!PyInt_Check(py_size))
|
||||
return Error_type_error(
|
||||
"size should be an integer, got %.200s", py_size);
|
||||
|
||||
size = PyLong_AsSize_t(py_size);
|
||||
size = PyInt_AsSize_t(py_size);
|
||||
error = git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, size);
|
||||
if (error < 0) {
|
||||
Error_set(error);
|
||||
return NULL;
|
||||
}
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
case GIT_OPT_GET_MWINDOW_MAPPED_LIMIT:
|
||||
{
|
||||
size_t limit;
|
||||
|
||||
error = git_libgit2_opts(GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, &limit);
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
return PyInt_FromSize_t(limit);
|
||||
}
|
||||
|
||||
case GIT_OPT_SET_MWINDOW_MAPPED_LIMIT:
|
||||
{
|
||||
size_t limit;
|
||||
PyObject *py_limit;
|
||||
|
||||
py_limit = PyTuple_GetItem(args, 1);
|
||||
if (!py_limit)
|
||||
return NULL;
|
||||
|
||||
if (PyInt_Check(py_limit)) {
|
||||
limit = PyInt_AsSize_t(py_limit);
|
||||
} else if (PyLong_Check(py_limit)) {
|
||||
limit = PyLong_AsSize_t(py_limit);
|
||||
} else {
|
||||
return Error_type_error(
|
||||
"limit should be an integer, got %.200s", py_limit);
|
||||
}
|
||||
|
||||
error = git_libgit2_opts(GIT_OPT_SET_MWINDOW_MAPPED_LIMIT, limit);
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
case GIT_OPT_SET_CACHE_OBJECT_LIMIT:
|
||||
{
|
||||
size_t limit;
|
||||
int object_type;
|
||||
PyObject *py_object_type, *py_limit;
|
||||
|
||||
py_object_type = PyTuple_GetItem(args, 1);
|
||||
if (!py_object_type)
|
||||
return NULL;
|
||||
|
||||
py_limit = PyTuple_GetItem(args, 2);
|
||||
if (!py_limit)
|
||||
return NULL;
|
||||
|
||||
if (!PyInt_Check(py_limit))
|
||||
return Error_type_error(
|
||||
"limit should be an integer, got %.200s", py_limit);
|
||||
|
||||
object_type = PyInt_AsLong(py_object_type);
|
||||
limit = PyInt_AsSize_t(py_limit);
|
||||
error = git_libgit2_opts(
|
||||
GIT_OPT_SET_CACHE_OBJECT_LIMIT, object_type, limit);
|
||||
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
case GIT_OPT_SET_CACHE_MAX_SIZE:
|
||||
{
|
||||
size_t max_size;
|
||||
PyObject *py_max_size;
|
||||
|
||||
py_max_size = PyTuple_GetItem(args, 1);
|
||||
if (!py_max_size)
|
||||
return NULL;
|
||||
|
||||
if (!PyInt_Check(py_max_size))
|
||||
return Error_type_error(
|
||||
"max_size should be an integer, got %.200s", py_max_size);
|
||||
|
||||
max_size = PyInt_AsSize_t(py_max_size);
|
||||
error = git_libgit2_opts(GIT_OPT_SET_CACHE_MAX_SIZE, max_size);
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
case GIT_OPT_ENABLE_CACHING:
|
||||
{
|
||||
int flag;
|
||||
PyObject *py_flag;
|
||||
|
||||
py_flag = PyTuple_GetItem(args, 1);
|
||||
|
||||
if (!PyInt_Check(py_flag))
|
||||
return Error_type_error(
|
||||
"flag should be an integer, got %.200s", py_flag);
|
||||
|
||||
flag = PyInt_AsSize_t(py_flag);
|
||||
error = git_libgit2_opts(GIT_OPT_ENABLE_CACHING, flag);
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
case GIT_OPT_GET_CACHED_MEMORY:
|
||||
{
|
||||
size_t current;
|
||||
size_t allowed;
|
||||
PyObject* tup = PyTuple_New(2);
|
||||
|
||||
error = git_libgit2_opts(GIT_OPT_GET_CACHED_MEMORY, ¤t, &allowed);
|
||||
if (error < 0)
|
||||
return Error_set(error);
|
||||
|
||||
PyTuple_SetItem(tup, 0, PyInt_FromLong(current));
|
||||
PyTuple_SetItem(tup, 1, PyInt_FromLong(allowed));
|
||||
|
||||
return tup;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PyErr_SetString(PyExc_ValueError, "unknown/unsupported option value");
|
||||
return NULL;
|
||||
|
||||
on_non_integer:
|
||||
PyErr_SetString(PyExc_TypeError, "option is not an integer");
|
||||
return NULL;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
60
src/pygit2.c
60
src/pygit2.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -144,7 +144,44 @@ hash(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(init_file_backend__doc__,
|
||||
"init_file_backend(path) -> object\n"
|
||||
"\n"
|
||||
"open repo backend given path.");
|
||||
PyObject *
|
||||
init_file_backend(PyObject *self, PyObject *args)
|
||||
{
|
||||
const char* path = NULL;
|
||||
int err = GIT_OK;
|
||||
git_repository *repository = NULL;
|
||||
if (!PyArg_ParseTuple(args, "s", &path)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = git_repository_open(&repository, path);
|
||||
if (err < 0) {
|
||||
Error_set_str(err, path);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
return PyCapsule_New(repository, "backend", NULL);
|
||||
|
||||
cleanup:
|
||||
if (repository) {
|
||||
git_repository_free(repository);
|
||||
}
|
||||
|
||||
if (err == GIT_ENOTFOUND) {
|
||||
PyErr_Format(GitError, "Repository not found at %s", path);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PyMethodDef module_methods[] = {
|
||||
{"init_file_backend", init_file_backend, METH_VARARGS,
|
||||
init_file_backend__doc__},
|
||||
{"discover_repository", discover_repository, METH_VARARGS,
|
||||
discover_repository__doc__},
|
||||
{"hashfile", hashfile, METH_VARARGS, hashfile__doc__},
|
||||
@ -170,6 +207,12 @@ moduleinit(PyObject* m)
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_SET_SEARCH_PATH);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_GET_MWINDOW_SIZE);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_SET_MWINDOW_SIZE);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_GET_MWINDOW_MAPPED_LIMIT);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_SET_MWINDOW_MAPPED_LIMIT);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_SET_CACHE_OBJECT_LIMIT);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_GET_CACHED_MEMORY);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_ENABLE_CACHING);
|
||||
ADD_CONSTANT_INT(m, GIT_OPT_SET_CACHE_MAX_SIZE);
|
||||
|
||||
/* Errors */
|
||||
GitError = PyErr_NewException("_pygit2.GitError", NULL, NULL);
|
||||
@ -260,6 +303,7 @@ moduleinit(PyObject* m)
|
||||
ADD_TYPE(m, Branch)
|
||||
ADD_CONSTANT_INT(m, GIT_BRANCH_LOCAL)
|
||||
ADD_CONSTANT_INT(m, GIT_BRANCH_REMOTE)
|
||||
ADD_CONSTANT_INT(m, GIT_BRANCH_ALL)
|
||||
|
||||
/*
|
||||
* Index & Working copy
|
||||
@ -323,6 +367,7 @@ moduleinit(PyObject* m)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_IGNORE_CASE)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_SHOW_UNTRACKED_CONTENT)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_SKIP_BINARY_CHECK)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_SHOW_BINARY)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_INCLUDE_TYPECHANGE_TREES)
|
||||
ADD_CONSTANT_INT(m, GIT_DIFF_RECURSE_IGNORED_DIRS)
|
||||
@ -380,6 +425,19 @@ moduleinit(PyObject* m)
|
||||
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_FASTFORWARD)
|
||||
ADD_CONSTANT_INT(m, GIT_MERGE_ANALYSIS_UNBORN)
|
||||
|
||||
/* Describe */
|
||||
ADD_CONSTANT_INT(m, GIT_DESCRIBE_DEFAULT);
|
||||
ADD_CONSTANT_INT(m, GIT_DESCRIBE_TAGS);
|
||||
ADD_CONSTANT_INT(m, GIT_DESCRIBE_ALL);
|
||||
|
||||
/* Stash */
|
||||
ADD_CONSTANT_INT(m, GIT_STASH_DEFAULT);
|
||||
ADD_CONSTANT_INT(m, GIT_STASH_KEEP_INDEX);
|
||||
ADD_CONSTANT_INT(m, GIT_STASH_INCLUDE_UNTRACKED);
|
||||
ADD_CONSTANT_INT(m, GIT_STASH_INCLUDE_IGNORED);
|
||||
ADD_CONSTANT_INT(m, GIT_STASH_APPLY_DEFAULT);
|
||||
ADD_CONSTANT_INT(m, GIT_STASH_APPLY_REINSTATE_INDEX);
|
||||
|
||||
/* Global initialization of libgit2 */
|
||||
git_libgit2_init();
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -325,7 +325,7 @@ Reference_type__get__(Reference *self)
|
||||
|
||||
CHECK_REFERENCE(self);
|
||||
c_type = git_reference_type(self->reference);
|
||||
return PyLong_FromLong(c_type);
|
||||
return PyInt_FromLong(c_type);
|
||||
}
|
||||
|
||||
|
||||
@ -379,7 +379,8 @@ PyDoc_STRVAR(Reference_peel__doc__,
|
||||
PyObject *
|
||||
Reference_peel(Reference *self, PyObject *args)
|
||||
{
|
||||
int err, type;
|
||||
int err;
|
||||
git_otype otype;
|
||||
git_object *obj;
|
||||
PyObject *py_type = Py_None;
|
||||
|
||||
@ -388,11 +389,11 @@ Reference_peel(Reference *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "|O", &py_type))
|
||||
return NULL;
|
||||
|
||||
type = py_object_to_object_type(py_type);
|
||||
if (type == -1)
|
||||
otype = py_object_to_otype(py_type);
|
||||
if (otype == GIT_OBJ_BAD)
|
||||
return NULL;
|
||||
|
||||
err = git_reference_peel(&obj, self->reference, type);
|
||||
err = git_reference_peel(&obj, self->reference, otype);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
318
src/repository.c
318
src/repository.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -88,8 +88,7 @@ wrap_repository(git_repository *c_repo)
|
||||
int
|
||||
Repository_init(Repository *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
char *path;
|
||||
int err;
|
||||
PyObject *backend;
|
||||
|
||||
if (kwds && PyDict_Size(kwds) > 0) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
@ -97,15 +96,16 @@ Repository_init(Repository *self, PyObject *args, PyObject *kwds)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &path))
|
||||
return -1;
|
||||
|
||||
err = git_repository_open(&self->repo, path);
|
||||
if (err < 0) {
|
||||
Error_set_str(err, path);
|
||||
if (!PyArg_ParseTuple(args, "O", &backend)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->repo = PyCapsule_GetPointer(backend, "backend");
|
||||
if (self->repo == NULL) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Repository unable to unpack backend.");
|
||||
return -1;
|
||||
}
|
||||
self->owned = 1;
|
||||
self->config = NULL;
|
||||
self->index = NULL;
|
||||
@ -349,6 +349,26 @@ Repository_lookup_branch(Repository *self, PyObject *args)
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_path_is_ignored__doc__,
|
||||
"Check if a path is ignored in the repository.");
|
||||
|
||||
PyObject *
|
||||
Repository_path_is_ignored(Repository *self, PyObject *args)
|
||||
{
|
||||
int ignored;
|
||||
char *path;
|
||||
|
||||
if (!PyArg_ParseTuple(args, "s", &path))
|
||||
return NULL;
|
||||
|
||||
git_ignore_path_is_ignored(&ignored, self->repo, path);
|
||||
if (ignored == 1)
|
||||
Py_RETURN_TRUE;
|
||||
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_revparse_single__doc__,
|
||||
"revparse_single(revision) -> Object\n"
|
||||
"\n"
|
||||
@ -842,6 +862,86 @@ Repository_create_blob_fromdisk(Repository *self, PyObject *args)
|
||||
}
|
||||
|
||||
|
||||
#define BUFSIZE 4096
|
||||
|
||||
PyDoc_STRVAR(Repository_create_blob_fromiobase__doc__,
|
||||
"create_blob_fromiobase(io.IOBase) -> Oid\n"
|
||||
"\n"
|
||||
"Create a new blob from an IOBase object.");
|
||||
|
||||
PyObject *
|
||||
Repository_create_blob_fromiobase(Repository *self, PyObject *py_file)
|
||||
{
|
||||
git_writestream *stream;
|
||||
git_oid oid;
|
||||
PyObject *py_is_readable;
|
||||
int is_readable;
|
||||
int err;
|
||||
|
||||
py_is_readable = PyObject_CallMethod(py_file, "readable", NULL);
|
||||
if (!py_is_readable) {
|
||||
if (PyErr_ExceptionMatches(PyExc_AttributeError))
|
||||
PyErr_SetObject(PyExc_TypeError, py_file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
is_readable = PyObject_IsTrue(py_is_readable);
|
||||
Py_DECREF(py_is_readable);
|
||||
|
||||
if (!is_readable) {
|
||||
Py_DECREF(py_file);
|
||||
PyErr_SetString(PyExc_TypeError, "expected readable IO type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = git_blob_create_fromstream(&stream, self->repo, NULL);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
for (;;) {
|
||||
PyObject *py_bytes;
|
||||
char *bytes;
|
||||
Py_ssize_t size;
|
||||
|
||||
py_bytes = PyObject_CallMethod(py_file, "read", "i", 4096);
|
||||
if (!py_bytes)
|
||||
return NULL;
|
||||
|
||||
if (py_bytes == Py_None) {
|
||||
Py_DECREF(py_bytes);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (PyBytes_AsStringAndSize(py_bytes, &bytes, &size)) {
|
||||
Py_DECREF(py_bytes);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (size == 0) {
|
||||
Py_DECREF(py_bytes);
|
||||
break;
|
||||
}
|
||||
|
||||
err = stream->write(stream, bytes, size);
|
||||
Py_DECREF(py_bytes);
|
||||
if (err < 0)
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
cleanup:
|
||||
if (err < 0) {
|
||||
stream->free(stream);
|
||||
return Error_set(err);
|
||||
}
|
||||
|
||||
err = git_blob_create_fromstream_commit(&oid, stream);
|
||||
if (err < 0)
|
||||
return Error_set(err);
|
||||
|
||||
return git_oid_to_python(&oid);
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_create_commit__doc__,
|
||||
"create_commit(reference_name, author, committer, message, tree, parents[, encoding]) -> Oid\n"
|
||||
"\n"
|
||||
@ -1041,6 +1141,56 @@ out:
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_listall_reference_objects__doc__,
|
||||
"listall_reference_objects() -> [Reference, ...]\n"
|
||||
"\n"
|
||||
"Return a list with all the reference objects in the repository.");
|
||||
|
||||
PyObject *
|
||||
Repository_listall_reference_objects(Repository *self, PyObject *args)
|
||||
{
|
||||
git_reference_iterator *iter;
|
||||
git_reference *ref = NULL;
|
||||
int err;
|
||||
PyObject *list;
|
||||
|
||||
list = PyList_New(0);
|
||||
if (list == NULL)
|
||||
return NULL;
|
||||
|
||||
if ((err = git_reference_iterator_new(&iter, self->repo)) < 0)
|
||||
return Error_set(err);
|
||||
|
||||
while ((err = git_reference_next(&ref, iter)) == 0) {
|
||||
PyObject *py_ref = wrap_reference(ref, self);
|
||||
if (py_ref == NULL)
|
||||
goto error;
|
||||
|
||||
err = PyList_Append(list, py_ref);
|
||||
Py_DECREF(py_ref);
|
||||
|
||||
if (err < 0)
|
||||
goto error;
|
||||
}
|
||||
|
||||
git_reference_iterator_free(iter);
|
||||
if (err == GIT_ITEROVER)
|
||||
err = 0;
|
||||
|
||||
if (err < 0) {
|
||||
Py_CLEAR(list);
|
||||
return Error_set(err);
|
||||
}
|
||||
|
||||
return list;
|
||||
|
||||
error:
|
||||
git_reference_iterator_free(iter);
|
||||
Py_CLEAR(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_listall_branches__doc__,
|
||||
"listall_branches([flag]) -> [str, ...]\n"
|
||||
"\n"
|
||||
@ -1137,6 +1287,141 @@ Repository_listall_submodules(Repository *self, PyObject *args)
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository_init_submodules__doc__,
|
||||
"init_submodule(submodules=None, overwrite=False)\n"
|
||||
"\n"
|
||||
"Initialize all submodules in repository.\n"
|
||||
"submodules: List of submodules to initialize. Default argument initializes all submodules.\n"
|
||||
"overwrite: Flag indicating if initialization should overwrite submodule entries.\n");
|
||||
|
||||
static int foreach_sub_init_cb(git_submodule *submodule, const char *name, void *payload)
|
||||
{
|
||||
return git_submodule_init(submodule, *(int*)payload);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
Repository_init_submodules(Repository* self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *list = Py_None;
|
||||
PyObject *oflag = Py_False;
|
||||
char *kwlist[] = {"submodules", "overwrite", NULL};
|
||||
int err, fflag;
|
||||
PyObject *iter, *subpath, *next;
|
||||
const char *c_subpath;
|
||||
git_submodule *submodule;
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &list, &oflag))
|
||||
return NULL;
|
||||
|
||||
fflag = PyObject_IsTrue(oflag);
|
||||
|
||||
if (fflag != 0 && fflag != 1)
|
||||
fflag = 0;
|
||||
|
||||
//Init all submodules listed in repository
|
||||
if (list == Py_None) {
|
||||
err = git_submodule_foreach(self->repo, foreach_sub_init_cb, &fflag);
|
||||
if (err != 0)
|
||||
return Error_set(err);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
iter = PyObject_GetIter(list);
|
||||
if (!iter)
|
||||
return NULL;
|
||||
|
||||
while (1) {
|
||||
next = PyIter_Next(iter);
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
c_subpath = py_str_borrow_c_str(&subpath, next, NULL);
|
||||
|
||||
git_submodule_lookup(&submodule, self->repo, c_subpath);
|
||||
Py_DECREF(subpath);
|
||||
if (!submodule) {
|
||||
PyErr_SetString(PyExc_KeyError,
|
||||
"Submodule does not exist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = git_submodule_init(submodule, fflag);
|
||||
if (err != 0) {
|
||||
return Error_set(err);
|
||||
}
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Repository_update_submodules__doc__,
|
||||
"update_submodules(submodules=None, init=False)\n"
|
||||
"\n"
|
||||
"Updates the specified submodules, or all if None are specified\n"
|
||||
"init: Flag indicating if submodules should be automatically initialized if necessary.\n");
|
||||
|
||||
static int foreach_sub_update_cb(git_submodule *submodule, const char *name, void *payload)
|
||||
{
|
||||
git_submodule_update_options opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
|
||||
return git_submodule_update(submodule, *(int*)payload, &opts);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
Repository_update_submodules(Repository *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
PyObject *list = Py_None;
|
||||
PyObject *py_init = Py_False;
|
||||
PyObject *iter, *next, *subpath;
|
||||
int init, err;
|
||||
const char *c_subpath;
|
||||
git_submodule *submodule;
|
||||
git_submodule_update_options opts = GIT_SUBMODULE_UPDATE_OPTIONS_INIT;
|
||||
|
||||
char *kwlist[] = {"submodules", "init", NULL};
|
||||
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist, &list, &py_init))
|
||||
return NULL;
|
||||
|
||||
init = PyObject_IsTrue(py_init);
|
||||
|
||||
if (init != 0 && init != 1)
|
||||
init = 0;
|
||||
|
||||
if (list == Py_None) {
|
||||
err = git_submodule_foreach(self->repo, foreach_sub_update_cb, &init);
|
||||
if (err != 0)
|
||||
return Error_set(err);
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
iter = PyObject_GetIter(list);
|
||||
if (!iter)
|
||||
return NULL;
|
||||
|
||||
while (1) {
|
||||
next = PyIter_Next(iter);
|
||||
if (!next)
|
||||
break;
|
||||
|
||||
c_subpath = py_str_borrow_c_str(&subpath, next, NULL);
|
||||
|
||||
git_submodule_lookup(&submodule, self->repo, c_subpath);
|
||||
Py_DECREF(subpath);
|
||||
if (!submodule) {
|
||||
PyErr_SetString(PyExc_KeyError,
|
||||
"Submodule does not exist");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
err = git_submodule_update(submodule, init, &opts);
|
||||
if (err != 0) {
|
||||
return Error_set(err);
|
||||
}
|
||||
}
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Repository_lookup_reference__doc__,
|
||||
"lookup_reference(name) -> Reference\n"
|
||||
"\n"
|
||||
@ -1278,7 +1563,7 @@ Repository_status(Repository *self)
|
||||
path = entry->head_to_index->old_file.path;
|
||||
else
|
||||
path = entry->index_to_workdir->old_file.path;
|
||||
status = PyLong_FromLong((long) entry->status);
|
||||
status = PyInt_FromLong((long) entry->status);
|
||||
|
||||
err = PyDict_SetItemString(dict, path, status);
|
||||
Py_CLEAR(status);
|
||||
@ -1320,7 +1605,7 @@ Repository_status_file(Repository *self, PyObject *value)
|
||||
free(path);
|
||||
return err_obj;
|
||||
}
|
||||
return PyLong_FromLong(status);
|
||||
return PyInt_FromLong(status);
|
||||
}
|
||||
|
||||
|
||||
@ -1493,8 +1778,8 @@ PyDoc_STRVAR(Repository_reset__doc__,
|
||||
"\n"
|
||||
"Resets current head to the provided oid.\n"
|
||||
"reset_type:\n"
|
||||
"GIT_RESET_SOFT: resets head to point to oid, but does not modfy working copy, and leaves the changes in the index.\n"
|
||||
"GIT_RESET_MIXED: resets head to point to oid, but does not modfy working copy. It empties the index too.\n"
|
||||
"GIT_RESET_SOFT: resets head to point to oid, but does not modify working copy, and leaves the changes in the index.\n"
|
||||
"GIT_RESET_MIXED: resets head to point to oid, but does not modify working copy. It empties the index too.\n"
|
||||
"GIT_RESET_HARD: resets head to point to oid, and resets too the working copy and the content of the index.\n");
|
||||
|
||||
PyObject *
|
||||
@ -1547,6 +1832,7 @@ PyMethodDef Repository_methods[] = {
|
||||
METHOD(Repository, create_blob, METH_VARARGS),
|
||||
METHOD(Repository, create_blob_fromworkdir, METH_VARARGS),
|
||||
METHOD(Repository, create_blob_fromdisk, METH_VARARGS),
|
||||
METHOD(Repository, create_blob_fromiobase, METH_O),
|
||||
METHOD(Repository, create_commit, METH_VARARGS),
|
||||
METHOD(Repository, create_tag, METH_VARARGS),
|
||||
METHOD(Repository, TreeBuilder, METH_VARARGS),
|
||||
@ -1560,7 +1846,10 @@ PyMethodDef Repository_methods[] = {
|
||||
METHOD(Repository, create_reference_direct, METH_VARARGS),
|
||||
METHOD(Repository, create_reference_symbolic, METH_VARARGS),
|
||||
METHOD(Repository, listall_references, METH_NOARGS),
|
||||
METHOD(Repository, listall_reference_objects, METH_NOARGS),
|
||||
METHOD(Repository, listall_submodules, METH_NOARGS),
|
||||
METHOD(Repository, init_submodules, METH_VARARGS | METH_KEYWORDS),
|
||||
METHOD(Repository, update_submodules, METH_VARARGS | METH_KEYWORDS),
|
||||
METHOD(Repository, lookup_reference, METH_O),
|
||||
METHOD(Repository, revparse_single, METH_O),
|
||||
METHOD(Repository, status, METH_NOARGS),
|
||||
@ -1570,6 +1859,7 @@ PyMethodDef Repository_methods[] = {
|
||||
METHOD(Repository, lookup_note, METH_VARARGS),
|
||||
METHOD(Repository, git_object_lookup_prefix, METH_O),
|
||||
METHOD(Repository, lookup_branch, METH_VARARGS),
|
||||
METHOD(Repository, path_is_ignored, METH_VARARGS),
|
||||
METHOD(Repository, listall_branches, METH_VARARGS),
|
||||
METHOD(Repository, create_branch, METH_VARARGS),
|
||||
METHOD(Repository, reset, METH_VARARGS),
|
||||
@ -1594,7 +1884,7 @@ PyGetSetDef Repository_getseters[] = {
|
||||
|
||||
|
||||
PyDoc_STRVAR(Repository__doc__,
|
||||
"Repository(path) -> Repository\n"
|
||||
"Repository(backend) -> Repository\n"
|
||||
"\n"
|
||||
"Git repository.");
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -58,6 +58,8 @@ PyObject* Repository_create_commit(Repository *self, PyObject *args);
|
||||
PyObject* Repository_create_tag(Repository *self, PyObject *args);
|
||||
PyObject* Repository_create_branch(Repository *self, PyObject *args);
|
||||
PyObject* Repository_listall_references(Repository *self, PyObject *args);
|
||||
PyObject* Repository_listall_reference_objects(Repository *self,
|
||||
PyObject *args);
|
||||
PyObject* Repository_listall_branches(Repository *self, PyObject *args);
|
||||
PyObject* Repository_lookup_reference(Repository *self, PyObject *py_name);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -38,7 +38,7 @@ Signature_init(Signature *self, PyObject *args, PyObject *kwds)
|
||||
{
|
||||
char *keywords[] = {"name", "email", "time", "offset", "encoding", NULL};
|
||||
PyObject *py_name, *tname;
|
||||
char *email, *encoding = "ascii";
|
||||
char *email, *encoding = "utf-8";
|
||||
const char *name;
|
||||
long long time = -1;
|
||||
int offset = 0;
|
||||
@ -96,10 +96,10 @@ Signature_dealloc(Signature *self)
|
||||
|
||||
PyDoc_STRVAR(Signature__pointer__doc__, "Get the signature's pointer. For internal use only.");
|
||||
PyObject *
|
||||
Signature__pointer__get__(Repository *self)
|
||||
Signature__pointer__get__(Signature *self)
|
||||
{
|
||||
/* Bytes means a raw buffer */
|
||||
return PyBytes_FromStringAndSize((char *) &self->repo, sizeof(git_repository *));
|
||||
return PyBytes_FromStringAndSize((char *) &self->signature, sizeof(git_signature *));
|
||||
}
|
||||
|
||||
PyDoc_STRVAR(Signature__encoding__doc__, "Encoding.");
|
||||
@ -158,7 +158,7 @@ PyDoc_STRVAR(Signature_time__doc__, "Unix time.");
|
||||
PyObject *
|
||||
Signature_time__get__(Signature *self)
|
||||
{
|
||||
return PyLong_FromLongLong(self->signature->when.time);
|
||||
return PyInt_FromLongLong(self->signature->when.time);
|
||||
}
|
||||
|
||||
|
||||
@ -167,7 +167,7 @@ PyDoc_STRVAR(Signature_offset__doc__, "Offset from UTC in minutes.");
|
||||
PyObject *
|
||||
Signature_offset__get__(Signature *self)
|
||||
{
|
||||
return PyLong_FromLong(self->signature->when.offset);
|
||||
return PyInt_FromLong(self->signature->when.offset);
|
||||
}
|
||||
|
||||
PyGetSetDef Signature_getseters[] = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -111,7 +111,11 @@ PyDoc_STRVAR(Tag__message__doc__, "Tag message (bytes).");
|
||||
PyObject *
|
||||
Tag__message__get__(Tag *self)
|
||||
{
|
||||
return PyBytes_FromString(git_tag_message(self->tag));
|
||||
const char *message;
|
||||
message = git_tag_message(self->tag);
|
||||
if (!message)
|
||||
Py_RETURN_NONE;
|
||||
return PyBytes_FromString(message);
|
||||
}
|
||||
|
||||
PyMethodDef Tag_methods[] = {
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
28
src/tree.c
28
src/tree.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -54,7 +54,7 @@ PyDoc_STRVAR(TreeEntry_filemode__doc__, "Filemode.");
|
||||
PyObject *
|
||||
TreeEntry_filemode__get__(TreeEntry *self)
|
||||
{
|
||||
return PyLong_FromLong(git_tree_entry_filemode(self->entry));
|
||||
return PyInt_FromLong(git_tree_entry_filemode(self->entry));
|
||||
}
|
||||
|
||||
|
||||
@ -67,6 +67,24 @@ TreeEntry_name__get__(TreeEntry *self)
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(TreeEntry__name__doc__, "Name (bytes).");
|
||||
|
||||
PyObject *
|
||||
TreeEntry__name__get__(TreeEntry *self)
|
||||
{
|
||||
return PyBytes_FromString(git_tree_entry_name(self->entry));
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(TreeEntry_type__doc__, "Type.");
|
||||
|
||||
PyObject *
|
||||
TreeEntry_type__get__(TreeEntry *self)
|
||||
{
|
||||
return to_path(git_object_type2string(git_tree_entry_type(self->entry)));
|
||||
}
|
||||
|
||||
|
||||
PyDoc_STRVAR(TreeEntry_id__doc__, "Object id.");
|
||||
|
||||
PyObject *
|
||||
@ -168,9 +186,11 @@ TreeEntry_repr(TreeEntry *self)
|
||||
PyGetSetDef TreeEntry_getseters[] = {
|
||||
GETTER(TreeEntry, filemode),
|
||||
GETTER(TreeEntry, name),
|
||||
GETTER(TreeEntry, _name),
|
||||
GETTER(TreeEntry, oid),
|
||||
GETTER(TreeEntry, id),
|
||||
GETTER(TreeEntry, hex),
|
||||
GETTER(TreeEntry, type),
|
||||
{NULL}
|
||||
};
|
||||
|
||||
@ -270,7 +290,7 @@ Tree_fix_index(Tree *self, PyObject *py_index)
|
||||
size_t len;
|
||||
long slen;
|
||||
|
||||
index = PyLong_AsLong(py_index);
|
||||
index = PyInt_AsLong(py_index);
|
||||
if (PyErr_Occurred())
|
||||
return -1;
|
||||
|
||||
@ -339,7 +359,7 @@ Tree_getitem(Tree *self, PyObject *value)
|
||||
int err;
|
||||
|
||||
/* Case 1: integer */
|
||||
if (PyLong_Check(value))
|
||||
if (PyInt_Check(value))
|
||||
return Tree_getitem_by_index(self, value);
|
||||
|
||||
/* Case 2: byte or text string */
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -32,8 +32,8 @@
|
||||
#include <Python.h>
|
||||
#include <git2.h>
|
||||
|
||||
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 23)
|
||||
#error You need a compatible libgit2 version (v0.23.x)
|
||||
#if !(LIBGIT2_VER_MAJOR == 0 && LIBGIT2_VER_MINOR == 26)
|
||||
#error You need a compatible libgit2 version (v0.26.x)
|
||||
#endif
|
||||
|
||||
/*
|
||||
|
56
src/utils.c
56
src/utils.c
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -83,8 +83,7 @@ py_str_borrow_c_str(PyObject **tvalue, PyObject *value, const char *encoding)
|
||||
}
|
||||
|
||||
/* Type error */
|
||||
PyErr_Format(PyExc_TypeError, "unexpected %.200s",
|
||||
Py_TYPE(value)->tp_name);
|
||||
Error_type_error("unexpected %.200s", value);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -94,7 +93,7 @@ py_str_borrow_c_str(PyObject **tvalue, PyObject *value, const char *encoding)
|
||||
PyObject *
|
||||
get_pylist_from_git_strarray(git_strarray *strarray)
|
||||
{
|
||||
int index;
|
||||
size_t index;
|
||||
PyObject *new_list;
|
||||
|
||||
new_list = PyList_New(strarray->count);
|
||||
@ -161,40 +160,39 @@ on_error:
|
||||
static git_otype
|
||||
py_type_to_git_type(PyTypeObject *py_type)
|
||||
{
|
||||
git_otype type = GIT_OBJ_BAD;
|
||||
if (py_type == &CommitType)
|
||||
return GIT_OBJ_COMMIT;
|
||||
else if (py_type == &TreeType)
|
||||
return GIT_OBJ_TREE;
|
||||
else if (py_type == &BlobType)
|
||||
return GIT_OBJ_BLOB;
|
||||
else if (py_type == &TagType)
|
||||
return GIT_OBJ_TAG;
|
||||
|
||||
if (py_type == &CommitType) {
|
||||
type = GIT_OBJ_COMMIT;
|
||||
} else if (py_type == &TreeType) {
|
||||
type = GIT_OBJ_TREE;
|
||||
} else if (py_type == &BlobType) {
|
||||
type = GIT_OBJ_BLOB;
|
||||
} else if (py_type == &TagType) {
|
||||
type = GIT_OBJ_TAG;
|
||||
}
|
||||
|
||||
return type;
|
||||
PyErr_SetString(PyExc_ValueError, "invalid target type");
|
||||
return GIT_OBJ_BAD; /* -1 */
|
||||
}
|
||||
|
||||
int
|
||||
py_object_to_object_type(PyObject *py_type)
|
||||
git_otype
|
||||
py_object_to_otype(PyObject *py_type)
|
||||
{
|
||||
int type = -1;
|
||||
long value;
|
||||
|
||||
if (py_type == Py_None)
|
||||
return GIT_OBJ_ANY;
|
||||
|
||||
if (PyLong_Check(py_type)) {
|
||||
type = PyLong_AsLong(py_type);
|
||||
if (type == -1 && PyErr_Occurred())
|
||||
return -1;
|
||||
} else if (PyType_Check(py_type)) {
|
||||
type = py_type_to_git_type((PyTypeObject *) py_type);
|
||||
if (PyInt_Check(py_type)) {
|
||||
value = PyInt_AsLong(py_type);
|
||||
if (value == -1 && PyErr_Occurred())
|
||||
return GIT_OBJ_BAD;
|
||||
|
||||
/* TODO Check whether the value is a valid value */
|
||||
return (git_otype)value;
|
||||
}
|
||||
|
||||
if (type == -1) {
|
||||
PyErr_SetString(PyExc_ValueError, "invalid target type");
|
||||
}
|
||||
if (PyType_Check(py_type))
|
||||
return py_type_to_git_type((PyTypeObject *) py_type);
|
||||
|
||||
return type;
|
||||
PyErr_SetString(PyExc_ValueError, "invalid target type");
|
||||
return GIT_OBJ_BAD; /* -1 */
|
||||
}
|
||||
|
37
src/utils.h
37
src/utils.h
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -40,14 +40,17 @@
|
||||
#endif
|
||||
|
||||
/* Python 2 support */
|
||||
#ifndef Py_hash_t
|
||||
#define Py_hash_t long
|
||||
#endif
|
||||
|
||||
#ifndef PyLong_AsSize_t
|
||||
#define PyLong_AsSize_t (size_t)PyLong_AsSsize_t
|
||||
#endif
|
||||
|
||||
#if PY_MAJOR_VERSION == 2
|
||||
#define PyLong_FromSize_t PyInt_FromSize_t
|
||||
#define PyLong_AsSize_t (size_t)PyInt_AsSsize_t
|
||||
#define PyLong_AsLong PyInt_AsLong
|
||||
#undef PyLong_Check
|
||||
#define PyLong_Check PyInt_Check
|
||||
#define PyLong_FromLong PyInt_FromLong
|
||||
#define PyInteger_Type PyInt_Type
|
||||
#define PyInt_AsSize_t (size_t)PyInt_AsLong
|
||||
#define PyInt_FromLongLong PyInt_FromLong
|
||||
#define PyBytes_AS_STRING PyString_AS_STRING
|
||||
#define PyBytes_AsString PyString_AsString
|
||||
#define PyBytes_AsStringAndSize PyString_AsStringAndSize
|
||||
@ -58,20 +61,18 @@
|
||||
#define to_path(x) to_bytes(x)
|
||||
#define to_encoding(x) to_bytes(x)
|
||||
#else
|
||||
#define PyInteger_Type PyLong_Type
|
||||
#define PyInt_Check PyLong_Check
|
||||
#define PyInt_FromSize_t PyLong_FromSize_t
|
||||
#define PyInt_FromLong PyLong_FromLong
|
||||
#define PyInt_FromLongLong PyLong_FromLongLong
|
||||
#define PyInt_AsLong PyLong_AsLong
|
||||
#define PyInt_AsSize_t PyLong_AsSize_t
|
||||
|
||||
#define to_path(x) to_unicode(x, Py_FileSystemDefaultEncoding, "strict")
|
||||
#define to_encoding(x) PyUnicode_DecodeASCII(x, strlen(x), "strict")
|
||||
#define PyString_FromFormat(s, ...) PyUnicode_FromFormat(s, __VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#ifdef PYPY_VERSION
|
||||
#define PyLong_AsSize_t (size_t)PyLong_AsUnsignedLong
|
||||
#endif
|
||||
|
||||
#ifndef Py_hash_t
|
||||
#define Py_hash_t long
|
||||
#endif
|
||||
|
||||
|
||||
#define CHECK_REFERENCE(self)\
|
||||
if (self->reference == NULL) {\
|
||||
@ -120,7 +121,7 @@ const char *py_str_borrow_c_str(PyObject **tvaue, PyObject *value, const char *e
|
||||
PyObject * get_pylist_from_git_strarray(git_strarray *strarray);
|
||||
int get_strarraygit_from_pylist(git_strarray *array, PyObject *pylist);
|
||||
|
||||
int py_object_to_object_type(PyObject *py_type);
|
||||
int py_object_to_otype(PyObject *py_type);
|
||||
|
||||
#define py_path_to_c_str(py_path) \
|
||||
py_str_to_c_str(py_path, Py_FileSystemDefaultEncoding)
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
@ -98,13 +98,13 @@ PyDoc_STRVAR(Walker_sort__doc__,
|
||||
PyObject *
|
||||
Walker_sort(Walker *self, PyObject *py_sort_mode)
|
||||
{
|
||||
int sort_mode;
|
||||
long sort_mode;
|
||||
|
||||
sort_mode = (int)PyLong_AsLong(py_sort_mode);
|
||||
sort_mode = PyInt_AsLong(py_sort_mode);
|
||||
if (sort_mode == -1 && PyErr_Occurred())
|
||||
return NULL;
|
||||
|
||||
git_revwalk_sorting(self->walk, sort_mode);
|
||||
git_revwalk_sorting(self->walk, (unsigned int)sort_mode);
|
||||
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2010-2014 The pygit2 contributors
|
||||
* Copyright 2010-2017 The pygit2 contributors
|
||||
*
|
||||
* This file is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
BIN
test/data/binaryfilerepo.tar
Normal file
BIN
test/data/binaryfilerepo.tar
Normal file
Binary file not shown.
Binary file not shown.
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -30,6 +30,7 @@
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
from os.path import dirname, join
|
||||
import io
|
||||
import unittest
|
||||
|
||||
import pygit2
|
||||
@ -112,6 +113,19 @@ class BlobTest(utils.RepoTestCase):
|
||||
self.assertTrue(isinstance(blob, pygit2.Blob))
|
||||
self.assertEqual(pygit2.GIT_OBJ_BLOB, blob.type)
|
||||
|
||||
def test_create_blob_fromiobase(self):
|
||||
self.assertRaises(TypeError, self.repo.create_blob_fromiobase, 'bad type')
|
||||
|
||||
f = io.BytesIO(BLOB_CONTENT)
|
||||
blob_oid = self.repo.create_blob_fromiobase(f)
|
||||
blob = self.repo[blob_oid]
|
||||
|
||||
self.assertTrue(isinstance(blob, pygit2.Blob))
|
||||
self.assertEqual(pygit2.GIT_OBJ_BLOB, blob.type)
|
||||
|
||||
self.assertEqual(blob_oid, blob.id)
|
||||
self.assertEqual(BLOB_SHA, blob_oid.hex)
|
||||
|
||||
def test_diff_blob(self):
|
||||
blob = self.repo[BLOB_SHA]
|
||||
old_blob = self.repo['3b18e512dba79e4c8300dd08aeb37f8e728b8dad']
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -39,6 +39,135 @@ I18N_LAST_COMMIT = '5470a671a80ac3789f1a6a8cefbcf43ce7af0563'
|
||||
ORIGIN_MASTER_COMMIT = '784855caf26449a1914d2cf62d12b9374d76ae78'
|
||||
|
||||
|
||||
class BranchesObjectTestCase(utils.RepoTestCase):
|
||||
def test_lookup_branch_local(self):
|
||||
branch = self.repo.branches['master']
|
||||
self.assertEqual(branch.target.hex, LAST_COMMIT)
|
||||
|
||||
branch = self.repo.branches.local['i18n']
|
||||
self.assertEqual(branch.target.hex, I18N_LAST_COMMIT)
|
||||
|
||||
self.assertTrue(self.repo.branches.get('not-exists') is None)
|
||||
|
||||
self.assertRaises(KeyError, lambda: self.repo.branches['not-exists'])
|
||||
|
||||
def test_listall_branches(self):
|
||||
branches = sorted(self.repo.branches)
|
||||
self.assertEqual(branches, ['i18n', 'master'])
|
||||
|
||||
def test_create_branch(self):
|
||||
commit = self.repo[LAST_COMMIT]
|
||||
reference = self.repo.branches.create('version1', commit)
|
||||
self.assertTrue('version1' in self.repo.branches)
|
||||
reference = self.repo.branches['version1']
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
# try to create existing reference
|
||||
self.assertRaises(ValueError,
|
||||
lambda: self.repo.branches.create('version1', commit))
|
||||
|
||||
# try to create existing reference with force
|
||||
reference = self.repo.branches.create('version1', commit, True)
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
def test_delete(self):
|
||||
self.repo.branches.delete('i18n')
|
||||
|
||||
self.assertTrue(self.repo.branches.get('i18n') is None)
|
||||
|
||||
def test_cant_delete_master(self):
|
||||
self.assertRaises(pygit2.GitError, lambda: self.repo.branches.delete('master'))
|
||||
|
||||
def test_branch_is_head_returns_true_if_branch_is_head(self):
|
||||
branch = self.repo.branches.get('master')
|
||||
self.assertTrue(branch.is_head())
|
||||
|
||||
def test_branch_is_head_returns_false_if_branch_is_not_head(self):
|
||||
branch = self.repo.branches.get('i18n')
|
||||
self.assertFalse(branch.is_head())
|
||||
|
||||
def test_branch_rename_succeeds(self):
|
||||
new_branch = self.repo.branches['i18n'].rename('new-branch')
|
||||
self.assertEqual(new_branch.target.hex, I18N_LAST_COMMIT)
|
||||
|
||||
new_branch_2 = self.repo.branches.get('new-branch')
|
||||
self.assertEqual(new_branch_2.target.hex, I18N_LAST_COMMIT)
|
||||
|
||||
def test_branch_rename_fails_if_destination_already_exists(self):
|
||||
original_branch = self.repo.branches.get('i18n')
|
||||
self.assertRaises(ValueError, lambda: original_branch.rename('master'))
|
||||
|
||||
def test_branch_rename_not_fails_if_force_is_true(self):
|
||||
original_branch = self.repo.branches.get('master')
|
||||
new_branch = original_branch.rename('i18n', True)
|
||||
self.assertEqual(new_branch.target.hex, LAST_COMMIT)
|
||||
|
||||
def test_branch_rename_fails_with_invalid_names(self):
|
||||
original_branch = self.repo.branches.get('i18n')
|
||||
self.assertRaises(ValueError,
|
||||
lambda: original_branch.rename('abc@{123'))
|
||||
|
||||
def test_branch_name(self):
|
||||
branch = self.repo.branches.get('master')
|
||||
self.assertEqual(branch.branch_name, 'master')
|
||||
self.assertEqual(branch.name, 'refs/heads/master')
|
||||
|
||||
branch = self.repo.branches.get('i18n')
|
||||
self.assertEqual(branch.branch_name, 'i18n')
|
||||
self.assertEqual(branch.name, 'refs/heads/i18n')
|
||||
|
||||
|
||||
class BranchesObjectEmptyRepoTestCase(utils.EmptyRepoTestCase):
|
||||
def setUp(self):
|
||||
super(utils.EmptyRepoTestCase, self).setUp()
|
||||
|
||||
remote = self.repo.remotes[0]
|
||||
remote.fetch()
|
||||
|
||||
def test_lookup_branch_remote(self):
|
||||
branch = self.repo.branches.remote.get('origin/master')
|
||||
self.assertEqual(branch.target.hex, ORIGIN_MASTER_COMMIT)
|
||||
|
||||
self.assertTrue(
|
||||
self.repo.branches.remote.get('origin/not-exists') is None)
|
||||
|
||||
def test_listall_branches(self):
|
||||
branches = sorted(self.repo.branches.remote)
|
||||
self.assertEqual(branches, ['origin/master'])
|
||||
|
||||
def test_branch_remote_name(self):
|
||||
self.repo.remotes[0].fetch()
|
||||
branch = self.repo.branches.remote['origin/master']
|
||||
self.assertEqual(branch.remote_name, 'origin')
|
||||
|
||||
def test_branch_upstream(self):
|
||||
self.repo.remotes[0].fetch()
|
||||
remote_master = self.repo.branches.remote['origin/master']
|
||||
master = self.repo.branches.create('master',
|
||||
self.repo[remote_master.target.hex])
|
||||
|
||||
self.assertTrue(master.upstream is None)
|
||||
master.upstream = remote_master
|
||||
self.assertEqual(master.upstream.branch_name, 'origin/master')
|
||||
|
||||
def set_bad_upstream():
|
||||
master.upstream = 2.5
|
||||
|
||||
self.assertRaises(TypeError, set_bad_upstream)
|
||||
|
||||
master.upstream = None
|
||||
self.assertTrue(master.upstream is None)
|
||||
|
||||
def test_branch_upstream_name(self):
|
||||
self.repo.remotes[0].fetch()
|
||||
remote_master = self.repo.branches.remote['origin/master']
|
||||
master = self.repo.branches.create('master',
|
||||
self.repo[remote_master.target.hex])
|
||||
|
||||
master.upstream = remote_master
|
||||
self.assertEqual(master.upstream_name, 'refs/remotes/origin/master')
|
||||
|
||||
|
||||
class BranchesTestCase(utils.RepoTestCase):
|
||||
def test_lookup_branch_local(self):
|
||||
branch = self.repo.lookup_branch('master')
|
||||
@ -88,6 +217,14 @@ class BranchesTestCase(utils.RepoTestCase):
|
||||
branch = self.repo.lookup_branch('i18n')
|
||||
self.assertFalse(branch.is_head())
|
||||
|
||||
def test_branch_is_checked_out_returns_true_if_branch_is_checked_out(self):
|
||||
branch = self.repo.lookup_branch('master')
|
||||
self.assertTrue(branch.is_checked_out())
|
||||
|
||||
def test_branch_is_checked_out_returns_false_if_branch_is_not_checked_out(self):
|
||||
branch = self.repo.lookup_branch('i18n')
|
||||
self.assertFalse(branch.is_checked_out())
|
||||
|
||||
def test_branch_rename_succeeds(self):
|
||||
original_branch = self.repo.lookup_branch('i18n')
|
||||
new_branch = original_branch.rename('new-branch')
|
||||
@ -159,6 +296,7 @@ class BranchesEmptyRepoTestCase(utils.EmptyRepoTestCase):
|
||||
|
||||
def set_bad_upstream():
|
||||
master.upstream = 2.5
|
||||
|
||||
self.assertRaises(TypeError, set_bad_upstream)
|
||||
|
||||
master.upstream = None
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -97,7 +97,7 @@ class ConfigTest(utils.RepoTestCase):
|
||||
|
||||
self.assertRaises(TypeError, lambda: config[()])
|
||||
self.assertRaises(TypeError, lambda: config[-4])
|
||||
self.assertRaisesWithArg(ValueError, "Invalid config item name 'abc'",
|
||||
self.assertRaisesWithArg(ValueError, "invalid config item name 'abc'",
|
||||
lambda: config['abc'])
|
||||
self.assertRaisesWithArg(KeyError, 'abc.def',
|
||||
lambda: config['abc.def'])
|
||||
@ -153,7 +153,7 @@ class ConfigTest(utils.RepoTestCase):
|
||||
new_file.write("[this]\n\tthat = foobar\n\tthat = foobeer\n")
|
||||
new_file.close()
|
||||
|
||||
config.add_file(CONFIG_FILENAME, 5)
|
||||
config.add_file(CONFIG_FILENAME, 6)
|
||||
self.assertTrue('this.that' in config)
|
||||
l = config.get_multivar('this.that', 'foo.*')
|
||||
self.assertEqual(2, len(list(l)))
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -70,32 +70,37 @@ class CredentialCreateTest(utils.NoRepoTestCase):
|
||||
|
||||
class CredentialCallback(utils.RepoTestCase):
|
||||
def test_callback(self):
|
||||
def credentials_cb(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
raise Exception("I don't know the password")
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
@staticmethod
|
||||
def credentials(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
raise Exception("I don't know the password")
|
||||
|
||||
remote = self.repo.create_remote("github", "https://github.com/github/github")
|
||||
remote.credentials = credentials_cb
|
||||
url = "https://github.com/github/github"
|
||||
remote = self.repo.create_remote("github", url)
|
||||
|
||||
self.assertRaises(Exception, remote.fetch)
|
||||
self.assertRaises(Exception, lambda: remote.fetch(callbacks=MyCallbacks()))
|
||||
|
||||
def test_bad_cred_type(self):
|
||||
def credentials_cb(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
return Keypair("git", "foo.pub", "foo", "sekkrit")
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
@staticmethod
|
||||
def credentials(url, username, allowed):
|
||||
self.assertTrue(allowed & GIT_CREDTYPE_USERPASS_PLAINTEXT)
|
||||
return Keypair("git", "foo.pub", "foo", "sekkrit")
|
||||
|
||||
remote = self.repo.create_remote("github", "https://github.com/github/github")
|
||||
remote.credentials = credentials_cb
|
||||
|
||||
self.assertRaises(TypeError, remote.fetch)
|
||||
url = "https://github.com/github/github"
|
||||
remote = self.repo.create_remote("github", url)
|
||||
self.assertRaises(TypeError, lambda: remote.fetch(callbacks=MyCallbacks()))
|
||||
|
||||
class CallableCredentialTest(utils.RepoTestCase):
|
||||
|
||||
def test_user_pass(self):
|
||||
remote = self.repo.create_remote("bb", "https://bitbucket.org/libgit2/testgitrepository.git")
|
||||
remote.credentials = UserPass("libgit2", "libgit2")
|
||||
credentials = UserPass("libgit2", "libgit2")
|
||||
callbacks = pygit2.RemoteCallbacks(credentials=credentials)
|
||||
|
||||
remote.fetch()
|
||||
url = "https://bitbucket.org/libgit2/testgitrepository.git"
|
||||
remote = self.repo.create_remote("bb", url)
|
||||
remote.fetch(callbacks=callbacks)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
106
test/test_describe.py
Normal file
106
test/test_describe.py
Normal file
@ -0,0 +1,106 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
# as published by the Free Software Foundation.
|
||||
#
|
||||
# In addition to the permissions in the GNU General Public License,
|
||||
# the authors give you unlimited permission to link the compiled
|
||||
# version of this file into combinations with other programs,
|
||||
# and to distribute those combinations without any restriction
|
||||
# coming from the use of this file. (The General Public License
|
||||
# restrictions do apply in other respects; for example, they cover
|
||||
# modification of the file, and distribution when not linked into
|
||||
# a combined executable.)
|
||||
#
|
||||
# This file is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; see the file COPYING. If not, write to
|
||||
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
|
||||
# Boston, MA 02110-1301, USA.
|
||||
|
||||
"""Tests for describing commits."""
|
||||
|
||||
from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
|
||||
from pygit2 import GIT_DESCRIBE_DEFAULT, GIT_DESCRIBE_TAGS, GIT_DESCRIBE_ALL
|
||||
import pygit2
|
||||
from . import utils
|
||||
|
||||
|
||||
def add_tag(repo, name, target):
|
||||
message = 'Example tag.\n'
|
||||
tagger = pygit2.Signature('John Doe', 'jdoe@example.com', 12347, 0)
|
||||
|
||||
sha = repo.create_tag(name, target, pygit2.GIT_OBJ_COMMIT, tagger, message)
|
||||
return sha
|
||||
|
||||
|
||||
class DescribeTest(utils.RepoTestCase):
|
||||
|
||||
def test_describe(self):
|
||||
add_tag(self.repo, 'thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertEqual('thetag-2-g2be5719', self.repo.describe())
|
||||
|
||||
def test_describe_without_ref(self):
|
||||
self.assertRaises(pygit2.GitError, self.repo.describe)
|
||||
|
||||
def test_describe_default_oid(self):
|
||||
self.assertEqual('2be5719', self.repo.describe(show_commit_oid_as_fallback=True))
|
||||
|
||||
def test_describe_strategies(self):
|
||||
self.assertEqual('heads/master', self.repo.describe(describe_strategy=GIT_DESCRIBE_ALL))
|
||||
|
||||
self.repo.create_reference('refs/tags/thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertRaises(KeyError, self.repo.describe)
|
||||
self.assertEqual('thetag-2-g2be5719', self.repo.describe(describe_strategy=GIT_DESCRIBE_TAGS))
|
||||
|
||||
def test_describe_pattern(self):
|
||||
add_tag(self.repo, 'private/tag1', '5ebeeebb320790caf276b9fc8b24546d63316533')
|
||||
add_tag(self.repo, 'public/tag2', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
|
||||
self.assertEqual('public/tag2-2-g2be5719', self.repo.describe(pattern='public/*'))
|
||||
|
||||
def test_describe_committish(self):
|
||||
add_tag(self.repo, 'thetag', 'acecd5ea2924a4b900e7e149496e1f4b57976e51')
|
||||
self.assertEqual('thetag-4-g2be5719', self.repo.describe(committish='HEAD'))
|
||||
self.assertEqual('thetag-1-g5ebeeeb', self.repo.describe(committish='HEAD^'))
|
||||
|
||||
self.assertEqual('thetag-4-g2be5719', self.repo.describe(committish=self.repo.head))
|
||||
|
||||
self.assertEqual('thetag-1-g6aaa262', self.repo.describe(committish='6aaa262e655dd54252e5813c8e5acd7780ed097d'))
|
||||
self.assertEqual('thetag-1-g6aaa262', self.repo.describe(committish='6aaa262'))
|
||||
|
||||
def test_describe_follows_first_branch_only(self):
|
||||
add_tag(self.repo, 'thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertRaises(KeyError, self.repo.describe, only_follow_first_parent=True)
|
||||
|
||||
def test_describe_abbreviated_size(self):
|
||||
add_tag(self.repo, 'thetag', '4ec4389a8068641da2d6578db0419484972284c8')
|
||||
self.assertEqual('thetag-2-g2be5719152d4f82c', self.repo.describe(abbreviated_size=16))
|
||||
self.assertEqual('thetag', self.repo.describe(abbreviated_size=0))
|
||||
|
||||
def test_describe_long_format(self):
|
||||
add_tag(self.repo, 'thetag', '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98')
|
||||
self.assertEqual('thetag-0-g2be5719', self.repo.describe(always_use_long_format=True))
|
||||
|
||||
|
||||
class DescribeDirtyWorkdirTest(utils.DirtyRepoTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(utils.DirtyRepoTestCase, self).setUp()
|
||||
add_tag(self.repo, 'thetag', 'a763aa560953e7cfb87ccbc2f536d665aa4dff22')
|
||||
|
||||
def test_describe(self):
|
||||
self.assertEqual('thetag', self.repo.describe())
|
||||
|
||||
def test_describe_with_dirty_suffix(self):
|
||||
self.assertEqual('thetag-dirty', self.repo.describe(dirty_suffix='-dirty'))
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -33,6 +33,7 @@ import unittest
|
||||
import pygit2
|
||||
from pygit2 import GIT_DIFF_INCLUDE_UNMODIFIED
|
||||
from pygit2 import GIT_DIFF_IGNORE_WHITESPACE, GIT_DIFF_IGNORE_WHITESPACE_EOL
|
||||
from pygit2 import GIT_DIFF_SHOW_BINARY
|
||||
from pygit2 import GIT_DELTA_RENAMED
|
||||
from . import utils
|
||||
from itertools import chain
|
||||
@ -63,6 +64,22 @@ index 297efb8..0000000
|
||||
-c/d contents
|
||||
"""
|
||||
|
||||
PATCH_BINARY = """diff --git a/binary_file b/binary_file
|
||||
index 86e5c10..b835d73 100644
|
||||
Binary files a/binary_file and b/binary_file differ
|
||||
"""
|
||||
|
||||
PATCH_BINARY_SHOW = """diff --git a/binary_file b/binary_file
|
||||
index 86e5c1008b5ce635d3e3fffa4434c5eccd8f00b6..b835d73543244b6694f36a8c5dfdffb71b153db7 100644
|
||||
GIT binary patch
|
||||
literal 8
|
||||
Pc${NM%FIhFs^kIy3n&7R
|
||||
|
||||
literal 8
|
||||
Pc${NM&PdElPvrst3ey5{
|
||||
|
||||
"""
|
||||
|
||||
DIFF_HEAD_TO_INDEX_EXPECTED = [
|
||||
'staged_changes',
|
||||
'staged_changes_file_deleted',
|
||||
@ -308,5 +325,15 @@ class DiffTest(utils.BareRepoTestCase):
|
||||
width=80)
|
||||
self.assertEqual(STATS_EXPECTED, formatted)
|
||||
|
||||
|
||||
class BinaryDiffTest(utils.BinaryFileRepoTestCase):
|
||||
def test_binary_diff(self):
|
||||
repo = self.repo
|
||||
diff = repo.diff('HEAD', 'HEAD^')
|
||||
self.assertEqual(PATCH_BINARY, diff.patch)
|
||||
diff = repo.diff('HEAD', 'HEAD^', flags=GIT_DIFF_SHOW_BINARY)
|
||||
self.assertEqual(PATCH_BINARY_SHOW, diff.patch)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -31,24 +31,81 @@ from __future__ import absolute_import
|
||||
from __future__ import unicode_literals
|
||||
import unittest
|
||||
import pygit2
|
||||
from pygit2 import GIT_OPT_GET_MWINDOW_SIZE, GIT_OPT_SET_MWINDOW_SIZE
|
||||
from pygit2 import GIT_OPT_GET_SEARCH_PATH, GIT_OPT_SET_SEARCH_PATH
|
||||
from pygit2 import GIT_CONFIG_LEVEL_SYSTEM, GIT_CONFIG_LEVEL_XDG, GIT_CONFIG_LEVEL_GLOBAL
|
||||
from pygit2 import (
|
||||
GIT_OBJ_BLOB,
|
||||
GIT_OPT_GET_MWINDOW_SIZE, GIT_OPT_SET_MWINDOW_SIZE,
|
||||
GIT_OPT_GET_SEARCH_PATH, GIT_OPT_SET_SEARCH_PATH,
|
||||
GIT_OPT_GET_MWINDOW_MAPPED_LIMIT, GIT_OPT_SET_MWINDOW_MAPPED_LIMIT,
|
||||
GIT_CONFIG_LEVEL_SYSTEM, GIT_CONFIG_LEVEL_XDG, GIT_CONFIG_LEVEL_GLOBAL,
|
||||
GIT_OPT_SET_CACHE_OBJECT_LIMIT,
|
||||
GIT_OPT_GET_CACHED_MEMORY,
|
||||
GIT_OPT_ENABLE_CACHING,
|
||||
)
|
||||
from pygit2 import option
|
||||
from . import utils
|
||||
|
||||
class OptionsTest(utils.NoRepoTestCase):
|
||||
|
||||
def __option(self, getter, setter, value):
|
||||
old_value = option(getter)
|
||||
option(setter, value)
|
||||
self.assertEqual(value, option(getter))
|
||||
# Reset to avoid side effects in later tests
|
||||
option(setter, old_value)
|
||||
|
||||
def __proxy(self, name, value):
|
||||
old_value = getattr(pygit2.settings, name)
|
||||
setattr(pygit2.settings, name, value)
|
||||
self.assertEqual(value, getattr(pygit2.settings, name))
|
||||
# Reset to avoid side effects in later tests
|
||||
setattr(pygit2.settings, name, old_value)
|
||||
|
||||
def test_mwindow_size(self):
|
||||
new_size = 200 * 1024
|
||||
option(GIT_OPT_SET_MWINDOW_SIZE, new_size)
|
||||
self.assertEqual(new_size, option(GIT_OPT_GET_MWINDOW_SIZE))
|
||||
self.__option(
|
||||
GIT_OPT_GET_MWINDOW_SIZE,
|
||||
GIT_OPT_SET_MWINDOW_SIZE,
|
||||
200 * 1024)
|
||||
|
||||
def test_mwindow_size_proxy(self):
|
||||
new_size = 300 * 1024
|
||||
pygit2.settings.mwindow_size = new_size
|
||||
self.__proxy('mwindow_size', 300 * 1024)
|
||||
|
||||
self.assertEqual(new_size, pygit2.settings.mwindow_size)
|
||||
def test_mwindow_mapped_limit_200(self):
|
||||
self.__option(
|
||||
GIT_OPT_GET_MWINDOW_MAPPED_LIMIT,
|
||||
GIT_OPT_SET_MWINDOW_MAPPED_LIMIT,
|
||||
200 * 1024)
|
||||
|
||||
def test_mwindow_mapped_limit_300(self):
|
||||
self.__proxy('mwindow_mapped_limit', 300 * 1024)
|
||||
|
||||
def test_cache_object_limit(self):
|
||||
new_limit = 2 * 1024
|
||||
option(GIT_OPT_SET_CACHE_OBJECT_LIMIT, GIT_OBJ_BLOB, new_limit)
|
||||
|
||||
def test_cache_object_limit_proxy(self):
|
||||
new_limit = 4 * 1024
|
||||
pygit2.settings.cache_object_limit(GIT_OBJ_BLOB, new_limit)
|
||||
|
||||
def test_cached_memory(self):
|
||||
value = option(GIT_OPT_GET_CACHED_MEMORY)
|
||||
self.assertEqual(value[1], 256 * 1024**2)
|
||||
|
||||
def test_cached_memory_proxy(self):
|
||||
self.assertEqual(pygit2.settings.cached_memory[1], 256 * 1024**2)
|
||||
|
||||
def test_enable_cache(self):
|
||||
option(GIT_OPT_ENABLE_CACHING, False)
|
||||
option(GIT_OPT_ENABLE_CACHING, True)
|
||||
|
||||
def test_enable_cache_proxy(self):
|
||||
pygit2.settings.enable_caching(False)
|
||||
pygit2.settings.enable_caching(True)
|
||||
|
||||
def test_cache_max_size_proxy(self):
|
||||
pygit2.settings.cache_max_size(128 * 1024**2)
|
||||
self.assertEqual(pygit2.settings.cached_memory[1], 128 * 1024**2)
|
||||
pygit2.settings.cache_max_size(256 * 1024**2)
|
||||
self.assertEqual(pygit2.settings.cached_memory[1], 256 * 1024**2)
|
||||
|
||||
def test_search_path(self):
|
||||
paths = [(GIT_CONFIG_LEVEL_GLOBAL, '/tmp/global'),
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -35,12 +35,213 @@ from pygit2 import GitError, GIT_REF_OID, GIT_REF_SYMBOLIC, Signature
|
||||
from pygit2 import Commit, Tree
|
||||
from . import utils
|
||||
|
||||
|
||||
LAST_COMMIT = '2be5719152d4f82c7302b1c0932d8e5f0a4a0e98'
|
||||
|
||||
|
||||
class ReferencesObjectTest(utils.RepoTestCase):
|
||||
def test_list_all_reference_objects(self):
|
||||
repo = self.repo
|
||||
|
||||
refs = [(ref.name, ref.target.hex)
|
||||
for ref in repo.references.objects]
|
||||
self.assertEqual(sorted(refs),
|
||||
[('refs/heads/i18n',
|
||||
'5470a671a80ac3789f1a6a8cefbcf43ce7af0563'),
|
||||
('refs/heads/master',
|
||||
'2be5719152d4f82c7302b1c0932d8e5f0a4a0e98')])
|
||||
|
||||
def test_list_all_references(self):
|
||||
repo = self.repo
|
||||
|
||||
# Without argument
|
||||
self.assertEqual(sorted(repo.references),
|
||||
['refs/heads/i18n', 'refs/heads/master'])
|
||||
|
||||
# We add a symbolic reference
|
||||
repo.create_reference('refs/tags/version1', 'refs/heads/master')
|
||||
self.assertEqual(sorted(repo.references),
|
||||
['refs/heads/i18n', 'refs/heads/master',
|
||||
'refs/tags/version1'])
|
||||
|
||||
def test_head(self):
|
||||
head = self.repo.head
|
||||
self.assertEqual(LAST_COMMIT, self.repo[head.target].hex)
|
||||
|
||||
def test_lookup_reference(self):
|
||||
repo = self.repo
|
||||
|
||||
refname = 'refs/foo'
|
||||
# Raise KeyError ?
|
||||
self.assertRaises(KeyError, lambda: self.repo.references[refname])
|
||||
|
||||
# Return None ?
|
||||
self.assertIsNone(self.repo.references.get(refname))
|
||||
|
||||
# Test a lookup
|
||||
reference = repo.references.get('refs/heads/master')
|
||||
self.assertEqual(reference.name, 'refs/heads/master')
|
||||
|
||||
def test_reference_get_sha(self):
|
||||
reference = self.repo.references['refs/heads/master']
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
def test_reference_set_sha(self):
|
||||
NEW_COMMIT = '5ebeeebb320790caf276b9fc8b24546d63316533'
|
||||
reference = self.repo.references.get('refs/heads/master')
|
||||
reference.set_target(NEW_COMMIT)
|
||||
self.assertEqual(reference.target.hex, NEW_COMMIT)
|
||||
|
||||
def test_reference_set_sha_prefix(self):
|
||||
NEW_COMMIT = '5ebeeebb320790caf276b9fc8b24546d63316533'
|
||||
reference = self.repo.references.get('refs/heads/master')
|
||||
reference.set_target(NEW_COMMIT[0:6])
|
||||
self.assertEqual(reference.target.hex, NEW_COMMIT)
|
||||
|
||||
def test_reference_get_type(self):
|
||||
reference = self.repo.references.get('refs/heads/master')
|
||||
self.assertEqual(reference.type, GIT_REF_OID)
|
||||
|
||||
def test_get_target(self):
|
||||
reference = self.repo.references.get('HEAD')
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
|
||||
def test_set_target(self):
|
||||
reference = self.repo.references.get('HEAD')
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
reference.set_target('refs/heads/i18n')
|
||||
self.assertEqual(reference.target, 'refs/heads/i18n')
|
||||
|
||||
def test_get_shorthand(self):
|
||||
reference = self.repo.references.get('refs/heads/master')
|
||||
self.assertEqual(reference.shorthand, 'master')
|
||||
reference = self.repo.references.create('refs/remotes/origin/master', LAST_COMMIT)
|
||||
self.assertEqual(reference.shorthand, 'origin/master')
|
||||
|
||||
def test_set_target_with_message(self):
|
||||
reference = self.repo.references.get('HEAD')
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
sig = Signature('foo', 'bar')
|
||||
self.repo.set_ident('foo', 'bar')
|
||||
msg = 'Hello log'
|
||||
reference.set_target('refs/heads/i18n', message=msg)
|
||||
self.assertEqual(reference.target, 'refs/heads/i18n')
|
||||
self.assertEqual(list(reference.log())[0].message, msg)
|
||||
self.assertEqualSignature(list(reference.log())[0].committer, sig)
|
||||
|
||||
def test_delete(self):
|
||||
repo = self.repo
|
||||
|
||||
# We add a tag as a new reference that points to "origin/master"
|
||||
reference = repo.references.create('refs/tags/version1', LAST_COMMIT)
|
||||
self.assertTrue('refs/tags/version1' in repo.references)
|
||||
|
||||
# And we delete it
|
||||
reference.delete()
|
||||
self.assertFalse('refs/tags/version1' in repo.references)
|
||||
|
||||
# Access the deleted reference
|
||||
self.assertRaises(GitError, getattr, reference, 'name')
|
||||
self.assertRaises(GitError, getattr, reference, 'type')
|
||||
self.assertRaises(GitError, getattr, reference, 'target')
|
||||
self.assertRaises(GitError, reference.delete)
|
||||
self.assertRaises(GitError, reference.resolve)
|
||||
self.assertRaises(GitError, reference.rename, "refs/tags/version2")
|
||||
|
||||
def test_rename(self):
|
||||
# We add a tag as a new reference that points to "origin/master"
|
||||
reference = self.repo.references.create('refs/tags/version1',
|
||||
LAST_COMMIT)
|
||||
self.assertEqual(reference.name, 'refs/tags/version1')
|
||||
reference.rename('refs/tags/version2')
|
||||
self.assertEqual(reference.name, 'refs/tags/version2')
|
||||
|
||||
# def test_reload(self):
|
||||
# name = 'refs/tags/version1'
|
||||
|
||||
# repo = self.repo
|
||||
# ref = repo.create_reference(name, "refs/heads/master", symbolic=True)
|
||||
# ref2 = repo.lookup_reference(name)
|
||||
# ref.delete()
|
||||
# self.assertEqual(ref2.name, name)
|
||||
# self.assertRaises(KeyError, ref2.reload)
|
||||
# self.assertRaises(GitError, getattr, ref2, 'name')
|
||||
|
||||
|
||||
def test_reference_resolve(self):
|
||||
reference = self.repo.references.get('HEAD')
|
||||
self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
|
||||
reference = reference.resolve()
|
||||
self.assertEqual(reference.type, GIT_REF_OID)
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
def test_reference_resolve_identity(self):
|
||||
head = self.repo.references.get('HEAD')
|
||||
ref = head.resolve()
|
||||
self.assertTrue(ref.resolve() is ref)
|
||||
|
||||
def test_create_reference(self):
|
||||
# We add a tag as a new reference that points to "origin/master"
|
||||
reference = self.repo.references.create('refs/tags/version1',
|
||||
LAST_COMMIT)
|
||||
refs = self.repo.references
|
||||
self.assertTrue('refs/tags/version1' in refs)
|
||||
reference = self.repo.references.get('refs/tags/version1')
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
# try to create existing reference
|
||||
self.assertRaises(ValueError, self.repo.references.create,
|
||||
'refs/tags/version1', LAST_COMMIT)
|
||||
|
||||
# try to create existing reference with force
|
||||
reference = self.repo.references.create('refs/tags/version1',
|
||||
LAST_COMMIT, force=True)
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
def test_create_symbolic_reference(self):
|
||||
repo = self.repo
|
||||
# We add a tag as a new symbolic reference that always points to
|
||||
# "refs/heads/master"
|
||||
reference = repo.references.create('refs/tags/beta',
|
||||
'refs/heads/master')
|
||||
self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
|
||||
# try to create existing symbolic reference
|
||||
self.assertRaises(ValueError, repo.references.create,
|
||||
'refs/tags/beta', 'refs/heads/master')
|
||||
|
||||
# try to create existing symbolic reference with force
|
||||
reference = repo.references.create('refs/tags/beta',
|
||||
'refs/heads/master', force=True)
|
||||
self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
|
||||
# def test_packall_references(self):
|
||||
# self.repo.packall_references()
|
||||
|
||||
|
||||
def test_get_object(self):
|
||||
repo = self.repo
|
||||
ref = repo.references.get('refs/heads/master')
|
||||
self.assertEqual(repo[ref.target].id, ref.get_object().id)
|
||||
|
||||
def test_peel(self):
|
||||
ref = self.repo.references.get('refs/heads/master')
|
||||
commit = ref.peel(Commit)
|
||||
self.assertEqual(commit.tree.id, ref.peel(Tree).id)
|
||||
|
||||
|
||||
class ReferencesTest(utils.RepoTestCase):
|
||||
def test_list_all_reference_objects(self):
|
||||
repo = self.repo
|
||||
|
||||
refs = [(ref.name, ref.target.hex)
|
||||
for ref in repo.listall_reference_objects()]
|
||||
self.assertEqual(sorted(refs),
|
||||
[('refs/heads/i18n',
|
||||
'5470a671a80ac3789f1a6a8cefbcf43ce7af0563'),
|
||||
('refs/heads/master',
|
||||
'2be5719152d4f82c7302b1c0932d8e5f0a4a0e98')])
|
||||
|
||||
def test_list_all_references(self):
|
||||
repo = self.repo
|
||||
@ -69,12 +270,10 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
reference = repo.lookup_reference('refs/heads/master')
|
||||
self.assertEqual(reference.name, 'refs/heads/master')
|
||||
|
||||
|
||||
def test_reference_get_sha(self):
|
||||
reference = self.repo.lookup_reference('refs/heads/master')
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
|
||||
def test_reference_set_sha(self):
|
||||
NEW_COMMIT = '5ebeeebb320790caf276b9fc8b24546d63316533'
|
||||
reference = self.repo.lookup_reference('refs/heads/master')
|
||||
@ -87,17 +286,14 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
reference.set_target(NEW_COMMIT[0:6])
|
||||
self.assertEqual(reference.target.hex, NEW_COMMIT)
|
||||
|
||||
|
||||
def test_reference_get_type(self):
|
||||
reference = self.repo.lookup_reference('refs/heads/master')
|
||||
self.assertEqual(reference.type, GIT_REF_OID)
|
||||
|
||||
|
||||
def test_get_target(self):
|
||||
reference = self.repo.lookup_reference('HEAD')
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
|
||||
|
||||
def test_set_target(self):
|
||||
reference = self.repo.lookup_reference('HEAD')
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
@ -140,7 +336,6 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
self.assertRaises(GitError, reference.resolve)
|
||||
self.assertRaises(GitError, reference.rename, "refs/tags/version2")
|
||||
|
||||
|
||||
def test_rename(self):
|
||||
# We add a tag as a new reference that points to "origin/master"
|
||||
reference = self.repo.create_reference('refs/tags/version1',
|
||||
@ -149,17 +344,16 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
reference.rename('refs/tags/version2')
|
||||
self.assertEqual(reference.name, 'refs/tags/version2')
|
||||
|
||||
# def test_reload(self):
|
||||
# name = 'refs/tags/version1'
|
||||
|
||||
# def test_reload(self):
|
||||
# name = 'refs/tags/version1'
|
||||
|
||||
# repo = self.repo
|
||||
# ref = repo.create_reference(name, "refs/heads/master", symbolic=True)
|
||||
# ref2 = repo.lookup_reference(name)
|
||||
# ref.delete()
|
||||
# self.assertEqual(ref2.name, name)
|
||||
# self.assertRaises(KeyError, ref2.reload)
|
||||
# self.assertRaises(GitError, getattr, ref2, 'name')
|
||||
# repo = self.repo
|
||||
# ref = repo.create_reference(name, "refs/heads/master", symbolic=True)
|
||||
# ref2 = repo.lookup_reference(name)
|
||||
# ref.delete()
|
||||
# self.assertEqual(ref2.name, name)
|
||||
# self.assertRaises(KeyError, ref2.reload)
|
||||
# self.assertRaises(GitError, getattr, ref2, 'name')
|
||||
|
||||
|
||||
def test_reference_resolve(self):
|
||||
@ -169,13 +363,11 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
self.assertEqual(reference.type, GIT_REF_OID)
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
|
||||
def test_reference_resolve_identity(self):
|
||||
head = self.repo.lookup_reference('HEAD')
|
||||
ref = head.resolve()
|
||||
self.assertTrue(ref.resolve() is ref)
|
||||
|
||||
|
||||
def test_create_reference(self):
|
||||
# We add a tag as a new reference that points to "origin/master"
|
||||
reference = self.repo.create_reference('refs/tags/version1',
|
||||
@ -194,7 +386,6 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
LAST_COMMIT, force=True)
|
||||
self.assertEqual(reference.target.hex, LAST_COMMIT)
|
||||
|
||||
|
||||
def test_create_symbolic_reference(self):
|
||||
repo = self.repo
|
||||
# We add a tag as a new symbolic reference that always points to
|
||||
@ -204,7 +395,6 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
|
||||
|
||||
# try to create existing symbolic reference
|
||||
self.assertRaises(ValueError, repo.create_reference,
|
||||
'refs/tags/beta', 'refs/heads/master')
|
||||
@ -215,9 +405,8 @@ class ReferencesTest(utils.RepoTestCase):
|
||||
self.assertEqual(reference.type, GIT_REF_SYMBOLIC)
|
||||
self.assertEqual(reference.target, 'refs/heads/master')
|
||||
|
||||
|
||||
# def test_packall_references(self):
|
||||
# self.repo.packall_references()
|
||||
# def test_packall_references(self):
|
||||
# self.repo.packall_references()
|
||||
|
||||
|
||||
def test_get_object(self):
|
||||
|
@ -1,6 +1,6 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
#
|
||||
# Copyright 2010-2014 The pygit2 contributors
|
||||
# Copyright 2010-2017 The pygit2 contributors
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License, version 2,
|
||||
@ -33,6 +33,7 @@ import pygit2
|
||||
import sys
|
||||
from pygit2 import Oid
|
||||
from . import utils
|
||||
import gc
|
||||
|
||||
try:
|
||||
import __pypy__
|
||||
@ -188,21 +189,6 @@ class RepositoryTest(utils.RepoTestCase):
|
||||
end = sys.getrefcount(self.repo)
|
||||
self.assertEqual(start, end)
|
||||
|
||||
def test_remote_callback_typecheck(self):
|
||||
remote = self.repo.remotes[0]
|
||||
remote.progress = 5
|
||||
self.assertRaises(TypeError, remote, 'fetch')
|
||||
|
||||
remote = self.repo.remotes[0]
|
||||
remote.transfer_progress = 5
|
||||
self.assertRaises(TypeError, remote, 'fetch')
|
||||
|
||||
remote = self.repo.remotes[0]
|
||||
remote.update_tips = 5
|
||||
self.assertRaises(TypeError, remote, 'fetch')
|
||||
|
||||
|
||||
|
||||
class EmptyRepositoryTest(utils.EmptyRepoTestCase):
|
||||
def test_fetch(self):
|
||||
remote = self.repo.remotes[0]
|
||||
@ -212,31 +198,37 @@ class EmptyRepositoryTest(utils.EmptyRepoTestCase):
|
||||
self.assertEqual(stats.received_objects, REMOTE_REPO_OBJECTS)
|
||||
|
||||
def test_transfer_progress(self):
|
||||
self.tp = None
|
||||
def tp_cb(stats):
|
||||
self.tp = stats
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
def transfer_progress(self, stats):
|
||||
self.tp = stats
|
||||
|
||||
callbacks = MyCallbacks()
|
||||
remote = self.repo.remotes[0]
|
||||
remote.transfer_progress = tp_cb
|
||||
stats = remote.fetch()
|
||||
self.assertEqual(stats.received_bytes, self.tp.received_bytes)
|
||||
self.assertEqual(stats.indexed_objects, self.tp.indexed_objects)
|
||||
self.assertEqual(stats.received_objects, self.tp.received_objects)
|
||||
stats = remote.fetch(callbacks=callbacks)
|
||||
self.assertEqual(stats.received_bytes, callbacks.tp.received_bytes)
|
||||
self.assertEqual(stats.indexed_objects, callbacks.tp.indexed_objects)
|
||||
self.assertEqual(stats.received_objects, callbacks.tp.received_objects)
|
||||
|
||||
def test_update_tips(self):
|
||||
remote = self.repo.remotes[0]
|
||||
self.i = 0
|
||||
self.tips = [('refs/remotes/origin/master', Oid(hex='0'*40),
|
||||
Oid(hex='784855caf26449a1914d2cf62d12b9374d76ae78')),
|
||||
('refs/tags/root', Oid(hex='0'*40),
|
||||
Oid(hex='3d2962987c695a29f1f80b6c3aa4ec046ef44369'))]
|
||||
tips = [('refs/remotes/origin/master', Oid(hex='0'*40),
|
||||
Oid(hex='784855caf26449a1914d2cf62d12b9374d76ae78')),
|
||||
('refs/tags/root', Oid(hex='0'*40),
|
||||
Oid(hex='3d2962987c695a29f1f80b6c3aa4ec046ef44369'))]
|
||||
|
||||
def ut_cb(name, old, new):
|
||||
self.assertEqual(self.tips[self.i], (name, old, new))
|
||||
self.i += 1
|
||||
class MyCallbacks(pygit2.RemoteCallbacks):
|
||||
def __init__(self, test_self, tips):
|
||||
self.test = test_self
|
||||
self.tips = tips
|
||||
self.i = 0
|
||||
|
||||
remote.update_tips = ut_cb
|
||||
remote.fetch()
|
||||
def update_tips(self, name, old, new):
|
||||
self.test.assertEqual(self.tips[self.i], (name, old, new))
|
||||
self.i += 1
|
||||
|
||||
callbacks = MyCallbacks(self, tips)
|
||||
remote.fetch(callbacks=callbacks)
|
||||
self.assertTrue(callbacks.i > 0)
|
||||
|
||||
class PushTestCase(unittest.TestCase):
|
||||
def setUp(self):
|
||||
@ -247,6 +239,11 @@ class PushTestCase(unittest.TestCase):
|
||||
self.remote = self.clone.create_remote('origin', self.origin.path)
|
||||
|
||||
def tearDown(self):
|
||||
self.origin = None
|
||||
self.clone = None
|
||||
self.remote = None
|
||||
gc.collect()
|
||||
|
||||
self.origin_ctxtmgr.__exit__(None, None, None)
|
||||
self.clone_ctxtmgr.__exit__(None, None, None)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user