Introduce libgit2 options

Allow setting and getting the mwindow size and search paths.
This commit is contained in:
Carlos Martín Nieto
2014-03-23 12:55:12 +01:00
parent 0e4a27284f
commit ab44196730
4 changed files with 306 additions and 0 deletions

185
src/options.c Normal file
View File

@@ -0,0 +1,185 @@
/*
* Copyright 2010-2014 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.
*/
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <structmember.h>
#include "error.h"
#include "types.h"
#include "utils.h"
extern PyObject *GitError;
static PyObject *
get_search_path(long level)
{
char *buf = NULL;
size_t len = 64;
PyObject *py_path;
int error;
do {
len *= 2;
char *tmp = realloc(buf, len);
if (!tmp) {
free(buf);
PyErr_NoMemory();
return NULL;
}
buf = tmp;
error = git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, level, buf, len);
} while(error == GIT_EBUFS);
if (error < 0) {
free(buf);
Error_set(error);
return NULL;
}
if (!buf)
return NULL;
py_path = to_unicode(buf, NULL, NULL);
free(buf);
if (!py_path)
return NULL;
return py_path;
}
PyObject *
option(PyObject *self, PyObject *args)
{
long option;
int error;
PyObject *py_option;
py_option = PyTuple_GetItem(args, 0);
if (!py_option)
return NULL;
if (!PyLong_Check(py_option))
goto on_non_integer;
option = PyLong_AsLong(py_option);
switch (option) {
case GIT_OPT_GET_SEARCH_PATH:
{
PyObject *py_level;
py_level = PyTuple_GetItem(args, 1);
if (!py_level)
return NULL;
if (!PyLong_Check(py_level))
goto on_non_integer;
return get_search_path(PyLong_AsLong(py_level));
break;
}
case GIT_OPT_SET_SEARCH_PATH:
{
PyObject *py_level, *py_path, *tpath;
const char *path;
int err;
py_level = PyTuple_GetItem(args, 1);
if (!py_level)
return NULL;
py_path = PyTuple_GetItem(args, 2);
if (!py_path)
return NULL;
if (!PyLong_Check(py_level))
goto on_non_integer;
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);
Py_DECREF(tpath);
if (err < 0) {
Error_set(err);
return NULL;
}
Py_RETURN_NONE;
break;
}
case GIT_OPT_GET_MWINDOW_SIZE:
{
size_t size;
if ((error = git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &size)) < 0) {
Error_set(error);
return NULL;
}
return PyLong_FromSize_t(size);
break;
}
case GIT_OPT_SET_MWINDOW_SIZE:
{
size_t size;
PyObject *py_size;
py_size = PyTuple_GetItem(args, 1);
if (!py_size)
return NULL;
if (!PyLong_Check(py_size))
goto on_non_integer;
size = PyLong_AsSize_t(py_size);
if ((error = git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, size)) < 0) {
Error_set(error);
return NULL;
}
Py_RETURN_NONE;
break;
}
}
PyErr_SetString(PyExc_ValueError, "unknown/unsupported option value");
return NULL;
on_non_integer:
PyErr_SetString(PyExc_TypeError, "option is not an integer");
return NULL;
}

51
src/options.h Normal file
View File

@@ -0,0 +1,51 @@
/*
* Copyright 2010-2014 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.
*/
#ifndef INCLUDE_pygit2_blame_h
#define INCLUDE_pygit2_blame_h
#define PY_SSIZE_T_CLEAN
#include <Python.h>
#include <git2.h>
#include "types.h"
PyDoc_STRVAR(option__doc__,
"Get or set a libgit2 option\n"
"Arguments:\n"
" (GIT_OPT_GET_SEARCH_PATH, level)\n"
" Get the config search path for the given level\n"
" (GIT_OPT_SET_SEARCH_PATH, level, path)\n"
" Set the config search path for the given level\n"
" (GIT_OPT_GET_MWINDOW_SIZE)\n"
" Get the maximum mmap window size\n"
" (GIT_OPT_SET_MWINDOW_SIZE, size)\n"
" Set the maximum mmap window size\n");
PyObject *option(PyObject *self, PyObject *args);
#endif

View File

@@ -39,6 +39,7 @@
#include "utils.h"
#include "repository.h"
#include "oid.h"
#include "options.h"
/* FIXME: This is for pypy */
#ifndef MAXPATHLEN
@@ -244,6 +245,7 @@ PyMethodDef module_methods[] = {
discover_repository__doc__},
{"hashfile", hashfile, METH_VARARGS, hashfile__doc__},
{"hash", hash, METH_VARARGS, hash__doc__},
{"option", option, METH_VARARGS, option__doc__},
{NULL}
};
@@ -259,6 +261,12 @@ moduleinit(PyObject* m)
ADD_CONSTANT_INT(m, LIBGIT2_VER_REVISION)
ADD_CONSTANT_STR(m, LIBGIT2_VERSION)
/* libgit2 options */
ADD_CONSTANT_INT(m, GIT_OPT_GET_SEARCH_PATH);
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);
/* Errors */
GitError = PyErr_NewException("_pygit2.GitError", NULL, NULL);
Py_INCREF(GitError);
@@ -424,6 +432,11 @@ moduleinit(PyObject* m)
ADD_CONSTANT_INT(m, GIT_DIFF_FIND_AND_BREAK_REWRITES)
/* Config */
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_LOCAL);
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_GLOBAL);
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_XDG);
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_SYSTEM);
INIT_TYPE(ConfigType, NULL, PyType_GenericNew)
INIT_TYPE(ConfigIterType, NULL, NULL)
ADD_TYPE(m, Config)

57
test/test_options.py Normal file
View File

@@ -0,0 +1,57 @@
# -*- coding: UTF-8 -*-
#
# Copyright 2010-2014 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 Blame objects."""
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 option
from . import utils
class OptionsTest(utils.NoRepoTestCase):
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))
def test_search_path(self):
paths = [(GIT_CONFIG_LEVEL_GLOBAL, '/tmp/global'),
(GIT_CONFIG_LEVEL_XDG, '/tmp/xdg'),
(GIT_CONFIG_LEVEL_SYSTEM, '/tmp/etc')]
for level, path in paths:
option(GIT_OPT_SET_SEARCH_PATH, level, path)
self.assertEqual(path, option(GIT_OPT_GET_SEARCH_PATH, level))
if __name__ == '__main__':
unittest.main()