8000 Introduce Refdb type by ddevault · Pull Request #982 · libgit2/pygit2 · GitHub
[go: up one dir, main page]

Skip to content

Introduce Refdb type #982

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Apr 2, 2020
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
RefdbBackend: Add tests and flush out a few bugs
  • Loading branch information
ddevault committed Mar 30, 2020
commit 57fd016c5746f610171aa3b42be089d6d3596d22
34 changes: 23 additions & 11 deletions src/refdb_backend.c
Original file line number Diff line number Diff line change
Expand Up @@ -595,25 +595,37 @@ RefdbBackend_write(RefdbBackend *self, PyObject *args)
Reference *ref;
int force;
Signature *who;
const git_signature *sig = NULL;
char *message, *old_target;
PyObject *py_old;
git_oid old;
git_oid _old, *old = NULL;
if (self->refdb_backend->write == NULL) {
Py_INCREF(Py_NotImplemented);
return Py_NotImplemented;
}

if (!PyArg_ParseTuple(args, "O!pO!sOs", &ReferenceType, &ref,
&force, &SignatureType, &who, &message, &py_old, &old_target))
if (!PyArg_ParseTuple(args, "O!pOzOz", &ReferenceType, &ref,
&force, &who, &message, &py_old, &old_target))
return NULL;

py_oid_to_git_oid(py_old, &old);
if ((PyObject *)py_old != Py_None) {
py_oid_to_git_oid(py_old, &_old);
old = &_old;
}

if ((PyObject *)who != Py_None) {
if (!PyObject_IsInstance((PyObject *)who, (PyObject *)&SignatureType)) {
PyErr_SetString(PyExc_TypeError,
"Signature must be type pygit2.Signature");
return NULL;
}
sig = who->signature;
}

err = self->refdb_backend->write(self->refdb_backend,
ref->reference, force, who->signature, message, &old, old_target);
if (err != 0) {
ref->reference, force, sig, message, old, old_target);
if (err != 0)
return Error_set(err);
}

Py_RETURN_NONE;
}
Expand Down Expand Up @@ -675,20 +687,20 @@ RefdbBackend_delete(RefdbBackend *self, PyObject *args)
py_oid_to_git_oid(py_old_id, &old_id);
err = self->refdb_backend->del(self->refdb_backend,
ref_name, &old_id, old_target);
Py_DECREF(py_old_id);
} else {
err = self->refdb_backend->del(self->refdb_backend,
ref_name, NULL, old_target);
}

if (err != 0)
if (err != 0) {
return Error_set(err);
}

Py_RETURN_NONE;
}

PyDoc_STRVAR(RefdbBackend_compress__doc__,
"delete(ref_name: str, old_id: Oid, old_target: str)\n"
"compress()\n"
"\n"
"Suggests that the implementation compress or optimize its references.\n"
"This behavior is implementation-specific.");
Expand Down Expand Up @@ -737,7 +749,7 @@ RefdbBackend_has_log(RefdbBackend *self, PyObject *_ref_name)
return Error_set(err);
}

if (err == 0) {
if (err == 1) {
Py_RETURN_TRUE;
} else {
Py_RETURN_FALSE;
Expand Down
121 changes: 121 additions & 0 deletions test/test_refdb_backend.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Copyright 2010-2020 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 Refdb objects."""

import os
import unittest

from pygit2 import Refdb, RefdbBackend, RefdbFsBackend, Repository
from pygit2 import Reference

from . import utils

# Note: the refdb abstraction from libgit2 is meant to provide information
# which libgit2 transforms into something more useful, and in general YMMV by
# using the backend directly. So some of these tests are a bit vague or
# incomplete, to avoid hitting the semi-valid states that refdbs produce by
# design.
class ProxyRefdbBackend(RefdbBackend):
def __init__(self, source):
self.source = source

def exists(self, ref):
print(self, self.source, ref)
return self.source.exists(ref)

def lookup(self, ref):
return self.source.lookup(ref)

def write(self, ref, force, who, message, old, old_target):
return self.source.write(ref, force, who, message, old, old_target)

def rename(self, old_name, new_name, force, who, message):
return self.source.rename(old_name, new_name, force, who, message)

def delete(self, ref_name, old_id, old_target):
return self.source.delete(ref_name, old_id, old_target)

def compress(self):
return self.source.compress()

def has_log(self, ref_name):
return self.source.has_log(ref_name)

def ensure_log(self, ref_name):
return self.source.ensure_log(ref_name)

def __iter__(self):
return iter(self.source)

class CustomRefdbBackendTest(utils.RepoTestCase):
def setUp(self):
super().setUp()
self.backend = ProxyRefdbBackend(RefdbFsBackend(self.repo))

def test_exists(self):
assert not self.backend.exists('refs/heads/does-not-exist')
assert self.backend.exists('refs/heads/master')

def test_lookup(self):
assert self.backend.lookup('refs/heads/does-not-exist') is None
assert self.backend.lookup('refs/heads/master').name == 'refs/heads/master'

def test_write(self):
master = self.backend.lookup('refs/heads/master')
commit = self.repo.get(master.target)
ref = Reference("refs/heads/test-write", master.target, None)
self.backend.write(ref, False, commit.author,
"Create test-write", None, None)
assert self.backend.lookup("refs/heads/test-write").target == master.target

def test_rename(self):
old_ref = self.backend.lookup('refs/heads/i18n')
target = self.repo.get(old_ref.target)
who = target.committer
self.backend.rename('refs/heads/i18n', 'refs/heads/intl',
False, target.committer, target.message)
assert self.backend.lookup('refs/heads/intl').target == target.id

def test_delete(self):
old = self.backend.lookup('refs/heads/i18n')
self.backend.delete('refs/heads/i18n', old.target, None)
assert not self.backend.lookup('refs/heads/i18n')

def test_compress(self):
repo = self.repo
packed_refs_file = os.path.join(self.repo_path, '.git', 'packed-refs')
assert not os.path.exists(packed_refs_file)
self.backend.compress()
assert os.path.exists(packed_refs_file)

def test_has_log(self):
assert self.backend.has_log('refs/heads/master')
assert not self.backend.has_log('refs/heads/does-not-exist')

def test_ensure_log(self):
assert not self.backend.has_log('refs/heads/new-log')
self.backend.ensure_log('refs/heads/new-log')
assert self.backend.has_log('refs/heads/new-log')
0