Skip to content

Commit ab44196

Browse files
committed
Introduce libgit2 options
Allow setting and getting the mwindow size and search paths.
1 parent 0e4a272 commit ab44196

File tree

4 files changed

+306
-0
lines changed

4 files changed

+306
-0
lines changed

src/options.c

+185
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
/*
2+
* Copyright 2010-2014 The pygit2 contributors
3+
*
4+
* This file is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License, version 2,
6+
* as published by the Free Software Foundation.
7+
*
8+
* In addition to the permissions in the GNU General Public License,
9+
* the authors give you unlimited permission to link the compiled
10+
* version of this file into combinations with other programs,
11+
* and to distribute those combinations without any restriction
12+
* coming from the use of this file. (The General Public License
13+
* restrictions do apply in other respects; for example, they cover
14+
* modification of the file, and distribution when not linked into
15+
* a combined executable.)
16+
*
17+
* This file is distributed in the hope that it will be useful, but
18+
* WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20+
* General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU General Public License
23+
* along with this program; see the file COPYING. If not, write to
24+
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
25+
* Boston, MA 02110-1301, USA.
26+
*/
27+
28+
#define PY_SSIZE_T_CLEAN
29+
#include <Python.h>
30+
#include <structmember.h>
31+
#include "error.h"
32+
#include "types.h"
33+
#include "utils.h"
34+
35+
extern PyObject *GitError;
36+
37+
static PyObject *
38+
get_search_path(long level)
39+
{
40+
char *buf = NULL;
41+
size_t len = 64;
42+
PyObject *py_path;
43+
int error;
44+
45+
do {
46+
len *= 2;
47+
char *tmp = realloc(buf, len);
48+
if (!tmp) {
49+
free(buf);
50+
PyErr_NoMemory();
51+
return NULL;
52+
}
53+
buf = tmp;
54+
55+
error = git_libgit2_opts(GIT_OPT_GET_SEARCH_PATH, level, buf, len);
56+
} while(error == GIT_EBUFS);
57+
58+
if (error < 0) {
59+
free(buf);
60+
Error_set(error);
61+
return NULL;
62+
}
63+
64+
if (!buf)
65+
return NULL;
66+
67+
py_path = to_unicode(buf, NULL, NULL);
68+
free(buf);
69+
70+
if (!py_path)
71+
return NULL;
72+
73+
return py_path;
74+
}
75+
76+
PyObject *
77+
option(PyObject *self, PyObject *args)
78+
{
79+
long option;
80+
int error;
81+
PyObject *py_option;
82+
83+
py_option = PyTuple_GetItem(args, 0);
84+
if (!py_option)
85+
return NULL;
86+
87+
if (!PyLong_Check(py_option))
88+
goto on_non_integer;
89+
90+
option = PyLong_AsLong(py_option);
91+
92+
switch (option) {
93+
case GIT_OPT_GET_SEARCH_PATH:
94+
{
95+
PyObject *py_level;
96+
97+
py_level = PyTuple_GetItem(args, 1);
98+
if (!py_level)
99+
return NULL;
100+
101+
if (!PyLong_Check(py_level))
102+
goto on_non_integer;
103+
104+
return get_search_path(PyLong_AsLong(py_level));
105+
break;
106+
}
107+
108+
case GIT_OPT_SET_SEARCH_PATH:
109+
{
110+
PyObject *py_level, *py_path, *tpath;
111+
const char *path;
112+
int err;
113+
114+
py_level = PyTuple_GetItem(args, 1);
115+
if (!py_level)
116+
return NULL;
117+
118+
py_path = PyTuple_GetItem(args, 2);
119+
if (!py_path)
120+
return NULL;
121+
122+
if (!PyLong_Check(py_level))
123+
goto on_non_integer;
124+
125+
path = py_str_borrow_c_str(&tpath, py_path, NULL);
126+
if (!path)
127+
return NULL;
128+
129+
err = git_libgit2_opts(GIT_OPT_SET_SEARCH_PATH, PyLong_AsLong(py_level), path);
130+
Py_DECREF(tpath);
131+
132+
if (err < 0) {
133+
Error_set(err);
134+
return NULL;
135+
}
136+
137+
Py_RETURN_NONE;
138+
break;
139+
}
140+
141+
case GIT_OPT_GET_MWINDOW_SIZE:
142+
{
143+
size_t size;
144+
145+
if ((error = git_libgit2_opts(GIT_OPT_GET_MWINDOW_SIZE, &size)) < 0) {
146+
Error_set(error);
147+
return NULL;
148+
}
149+
150+
return PyLong_FromSize_t(size);
151+
152+
break;
153+
}
154+
155+
case GIT_OPT_SET_MWINDOW_SIZE:
156+
{
157+
size_t size;
158+
PyObject *py_size;
159+
160+
py_size = PyTuple_GetItem(args, 1);
161+
if (!py_size)
162+
return NULL;
163+
164+
if (!PyLong_Check(py_size))
165+
goto on_non_integer;
166+
167+
168+
size = PyLong_AsSize_t(py_size);
169+
if ((error = git_libgit2_opts(GIT_OPT_SET_MWINDOW_SIZE, size)) < 0) {
170+
Error_set(error);
171+
return NULL;
172+
}
173+
174+
Py_RETURN_NONE;
175+
break;
176+
}
177+
}
178+
179+
PyErr_SetString(PyExc_ValueError, "unknown/unsupported option value");
180+
return NULL;
181+
182+
on_non_integer:
183+
PyErr_SetString(PyExc_TypeError, "option is not an integer");
184+
return NULL;
185+
}

src/options.h

+51
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
/*
2+
* Copyright 2010-2014 The pygit2 contributors
3+
*
4+
* This file is free software; you can redistribute it and/or modify
5+
* it under the terms of the GNU General Public License, version 2,
6+
* as published by the Free Software Foundation.
7+
*
8+
* In addition to the permissions in the GNU General Public License,
9+
* the authors give you unlimited permission to link the compiled
10+
* version of this file into combinations with other programs,
11+
* and to distribute those combinations without any restriction
12+
* coming from the use of this file. (The General Public License
13+
* restrictions do apply in other respects; for example, they cover
14+
* modification of the file, and distribution when not linked into
15+
* a combined executable.)
16+
*
17+
* This file is distributed in the hope that it will be useful, but
18+
* WITHOUT ANY WARRANTY; without even the implied warranty of
19+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20+
* General Public License for more details.
21+
*
22+
* You should have received a copy of the GNU General Public License
23+
* along with this program; see the file COPYING. If not, write to
24+
* the Free Software Foundation, 51 Franklin Street, Fifth Floor,
25+
* Boston, MA 02110-1301, USA.
26+
*/
27+
28+
#ifndef INCLUDE_pygit2_blame_h
29+
#define INCLUDE_pygit2_blame_h
30+
31+
#define PY_SSIZE_T_CLEAN
32+
#include <Python.h>
33+
#include <git2.h>
34+
#include "types.h"
35+
36+
PyDoc_STRVAR(option__doc__,
37+
"Get or set a libgit2 option\n"
38+
"Arguments:\n"
39+
" (GIT_OPT_GET_SEARCH_PATH, level)\n"
40+
" Get the config search path for the given level\n"
41+
" (GIT_OPT_SET_SEARCH_PATH, level, path)\n"
42+
" Set the config search path for the given level\n"
43+
" (GIT_OPT_GET_MWINDOW_SIZE)\n"
44+
" Get the maximum mmap window size\n"
45+
" (GIT_OPT_SET_MWINDOW_SIZE, size)\n"
46+
" Set the maximum mmap window size\n");
47+
48+
49+
PyObject *option(PyObject *self, PyObject *args);
50+
51+
#endif

src/pygit2.c

+13
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "utils.h"
4040
#include "repository.h"
4141
#include "oid.h"
42+
#include "options.h"
4243

4344
/* FIXME: This is for pypy */
4445
#ifndef MAXPATHLEN
@@ -244,6 +245,7 @@ PyMethodDef module_methods[] = {
244245
discover_repository__doc__},
245246
{"hashfile", hashfile, METH_VARARGS, hashfile__doc__},
246247
{"hash", hash, METH_VARARGS, hash__doc__},
248+
{"option", option, METH_VARARGS, option__doc__},
247249
{NULL}
248250
};
249251

@@ -259,6 +261,12 @@ moduleinit(PyObject* m)
259261
ADD_CONSTANT_INT(m, LIBGIT2_VER_REVISION)
260262
ADD_CONSTANT_STR(m, LIBGIT2_VERSION)
261263

264+
/* libgit2 options */
265+
ADD_CONSTANT_INT(m, GIT_OPT_GET_SEARCH_PATH);
266+
ADD_CONSTANT_INT(m, GIT_OPT_SET_SEARCH_PATH);
267+
ADD_CONSTANT_INT(m, GIT_OPT_GET_MWINDOW_SIZE);
268+
ADD_CONSTANT_INT(m, GIT_OPT_SET_MWINDOW_SIZE);
269+
262270
/* Errors */
263271
GitError = PyErr_NewException("_pygit2.GitError", NULL, NULL);
264272
Py_INCREF(GitError);
@@ -424,6 +432,11 @@ moduleinit(PyObject* m)
424432
ADD_CONSTANT_INT(m, GIT_DIFF_FIND_AND_BREAK_REWRITES)
425433

426434
/* Config */
435+
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_LOCAL);
436+
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_GLOBAL);
437+
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_XDG);
438+
ADD_CONSTANT_INT(m, GIT_CONFIG_LEVEL_SYSTEM);
439+
427440
INIT_TYPE(ConfigType, NULL, PyType_GenericNew)
428441
INIT_TYPE(ConfigIterType, NULL, NULL)
429442
ADD_TYPE(m, Config)

test/test_options.py

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# -*- coding: UTF-8 -*-
2+
#
3+
# Copyright 2010-2014 The pygit2 contributors
4+
#
5+
# This file is free software; you can redistribute it and/or modify
6+
# it under the terms of the GNU General Public License, version 2,
7+
# as published by the Free Software Foundation.
8+
#
9+
# In addition to the permissions in the GNU General Public License,
10+
# the authors give you unlimited permission to link the compiled
11+
# version of this file into combinations with other programs,
12+
# and to distribute those combinations without any restriction
13+
# coming from the use of this file. (The General Public License
14+
# restrictions do apply in other respects; for example, they cover
15+
# modification of the file, and distribution when not linked into
16+
# a combined executable.)
17+
#
18+
# This file is distributed in the hope that it will be useful, but
19+
# WITHOUT ANY WARRANTY; without even the implied warranty of
20+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
21+
# General Public License for more details.
22+
#
23+
# You should have received a copy of the GNU General Public License
24+
# along with this program; see the file COPYING. If not, write to
25+
# the Free Software Foundation, 51 Franklin Street, Fifth Floor,
26+
# Boston, MA 02110-1301, USA.
27+
28+
"""Tests for Blame objects."""
29+
30+
from __future__ import absolute_import
31+
from __future__ import unicode_literals
32+
import unittest
33+
import pygit2
34+
from pygit2 import GIT_OPT_GET_MWINDOW_SIZE, GIT_OPT_SET_MWINDOW_SIZE
35+
from pygit2 import GIT_OPT_GET_SEARCH_PATH, GIT_OPT_SET_SEARCH_PATH
36+
from pygit2 import GIT_CONFIG_LEVEL_SYSTEM, GIT_CONFIG_LEVEL_XDG, GIT_CONFIG_LEVEL_GLOBAL
37+
from pygit2 import option
38+
from . import utils
39+
40+
class OptionsTest(utils.NoRepoTestCase):
41+
42+
def test_mwindow_size(self):
43+
new_size = 200 * 1024
44+
option(GIT_OPT_SET_MWINDOW_SIZE, new_size)
45+
self.assertEqual(new_size, option(GIT_OPT_GET_MWINDOW_SIZE))
46+
47+
def test_search_path(self):
48+
paths = [(GIT_CONFIG_LEVEL_GLOBAL, '/tmp/global'),
49+
(GIT_CONFIG_LEVEL_XDG, '/tmp/xdg'),
50+
(GIT_CONFIG_LEVEL_SYSTEM, '/tmp/etc')]
51+
52+
for level, path in paths:
53+
option(GIT_OPT_SET_SEARCH_PATH, level, path)
54+
self.assertEqual(path, option(GIT_OPT_GET_SEARCH_PATH, level))
55+
56+
if __name__ == '__main__':
57+
unittest.main()

0 commit comments

Comments
 (0)