3 static PyObject *PackIndexFile_sha_to_index(PyObject *self, PyObject *args)
4 {
5 const unsigned char *sha;
6 const unsigned int sha_len;
7
8 // Note: self is only set if we are a c type. We emulate an instance method,
9 // hence we have to get the instance as 'first' argument
10
11 // get instance and sha
12 PyObject* inst = 0;
13 if (!PyArg_ParseTuple(args, "Os#", &inst, &sha, &sha_len))
14 return NULL;
when PyArg_ParseTuple() succeeds
taking False path
15
16 if (sha_len != 20) {
17 PyErr_SetString(PyExc_ValueError, "Sha is not 20 bytes long");
when considering value == (int)20 from gitdb/_fun.c:14
taking False path
18 return NULL;
19 }
20
21 if( !inst){
22 PyErr_SetString(PyExc_ValueError, "Cannot be called without self");
taking False path
23 return NULL;
24 }
25
26 // read lo and hi bounds
27 PyObject* fanout_table = PyObject_GetAttrString(inst, "_fanout_table");
28 if (!fanout_table){
when PyObject_GetAttrString() succeeds
29 PyErr_SetString(PyExc_ValueError, "Couldn't obtain fanout table");
taking False path
30 return NULL;
31 }
32
33 unsigned int lo = 0, hi = 0;
34 if (sha[0]){
35 PyObject* item = PySequence_GetItem(fanout_table, (const Py_ssize_t)(sha[0]-1));
when treating unknown const char * from gitdb/_fun.c:14 as non-NULL
when considering value == (const unsigned char)0 from gitdb/_fun.c:35
taking False path
36 lo = PyInt_AS_LONG(item);
37 Py_DECREF(item);
38 }
39 PyObject* item = PySequence_GetItem(fanout_table, (const Py_ssize_t)sha[0]);
40 hi = PyInt_AS_LONG(item);
when PySequence_GetItem() succeeds
41 Py_DECREF(item);
42 item = 0;
when taking True path
43
44 Py_DECREF(fanout_table);
45
when taking True path
46 // get sha query function
47 PyObject* get_sha = PyObject_GetAttrString(inst, "sha");
48 if (!get_sha){
when PyObject_GetAttrString() succeeds
new ref from call to PyObject_GetAttrString allocated at: PyObject* get_sha = PyObject_GetAttrString(inst, "sha");
ob_refcnt is now refs: 1 + N where N >= 0
49 PyErr_SetString(PyExc_ValueError, "Couldn't obtain sha method");
taking False path
50 return NULL;
51 }
52
53 PyObject *sha_str = 0;
54 while (lo < hi) {
55 const int mid = (lo + hi)/2;
when considering range: 1 <= hi <= 0xffffffff
taking True path
56 sha_str = PyObject_CallFunction(get_sha, "i", mid);
57 if (!sha_str) {
when PyObject_CallFunction() fails
58 return NULL;
taking True path
59 }
60
61 // we really trust that string ... for speed
62 const int cmp = memcmp(PyString_AS_STRING(sha_str), sha, 20);
63 Py_DECREF(sha_str);
64 sha_str = 0;
65
66 if (cmp < 0){
67 lo = mid + 1;
68 }
69 else if (cmp > 0) {
70 hi = mid;
71 }
72 else {
73 Py_DECREF(get_sha);
74 return PyInt_FromLong(mid);
75 }// END handle comparison
76 }// END while lo < hi
77
78 // nothing found, cleanup
79 Py_DECREF(get_sha);
80 Py_RETURN_NONE;
81 }
82