2 #include "structmember.h"
4 #include <libgit-thin.h>
6 static PyObject
*PyGitError
;
8 PyMODINIT_FUNC
initpygit(void);
11 * Useful helpers for all the types
14 #define UNUSED(x) (x = x)
19 return PyErr_Format(PyGitError
, "[Errno: %d] %s", errno
,
24 pyarg_to_sha1(PyObject
*args
, unsigned char *sha1
)
28 if (!PyArg_ParseTuple(args
, "s", &hex
))
31 if (git_hex_to_sha1(hex
, sha1
)) {
40 sha1_to_pystr(unsigned char *sha1
)
42 char hex
[GIT_HEX_LENGTH
+ 1];
44 if (git_sha1_to_hex(sha1
, hex
))
47 return PyString_FromString(hex
);
56 struct git_commit
*commit
;
60 pygit_call_commit_op(struct git_commit
*commit
,
61 const char *(*commit_op
)(struct git_commit
*))
65 ret
= commit_op(commit
);
69 return PyString_FromString(ret
);
72 PyDoc_STRVAR(cmessage_doc
,
73 "commit.message() -> string\n\
75 Return the commit's message.");
78 commit_message(GitCommitObject
*self
, PyObject
*args
)
81 return pygit_call_commit_op(self
->commit
, git_commit_message
);
84 PyDoc_STRVAR(ccommitter_email_doc
,
85 "commit.committer_email() -> string\n\
87 Return the commit's committer e-mail.");
90 commit_committer_email(GitCommitObject
*self
, PyObject
*args
)
93 return pygit_call_commit_op(self
->commit
, git_commit_committer_email
);
96 PyDoc_STRVAR(ccommitter_name_doc
,
97 "commit.committer_name() -> string\n\
99 Return the commit's committer name.");
102 commit_committer_name(GitCommitObject
*self
, PyObject
*args
)
105 return pygit_call_commit_op(self
->commit
, git_commit_committer_name
);
108 PyDoc_STRVAR(cauthor_email_doc
,
109 "commit.author_email() -> string\n\
111 Return the commit's author e-mail.");
114 commit_author_email(GitCommitObject
*self
, PyObject
*args
)
117 return pygit_call_commit_op(self
->commit
, git_commit_author_email
);
120 PyDoc_STRVAR(cauthor_name_doc
,
121 "commit.author_name() -> string\n\
123 Return the commit's author name.");
126 commit_author_name(GitCommitObject
*self
, PyObject
*args
)
129 return pygit_call_commit_op(self
->commit
, git_commit_author_name
);
132 PyDoc_STRVAR(commit_raw_doc
,
133 "commit.buffer() -> string\n\
135 Return the commit's raw buffer.");
138 commit_raw(GitCommitObject
*self
, PyObject
*args
)
141 return pygit_call_commit_op(self
->commit
, git_commit_raw
);
145 pygit_call_commit_op_sha1(struct git_commit
*commit
,
146 int (*commit_op
)(struct git_commit
*,
147 unsigned char *sha1
))
150 unsigned char sha1
[GIT_SHA1_SIZE
];
152 err
= commit_op(commit
, sha1
);
154 return pygit_error();
156 return sha1_to_pystr(sha1
);
159 PyDoc_STRVAR(commit_id_doc
,
160 "commit.id() -> string\n\
162 Return the commit's SHA1 hex representation.");
165 commit_id(GitCommitObject
*self
, PyObject
*args
)
168 return pygit_call_commit_op_sha1(self
->commit
, git_commit_id
);
171 PyDoc_STRVAR(commit_tree_doc
,
172 "commit.tree() -> string\n\
174 Return the commit's tree SHA1 hex representation.");
177 commit_tree(GitCommitObject
*self
, PyObject
*args
)
180 return pygit_call_commit_op_sha1(self
->commit
, git_commit_tree
);
183 static PyMethodDef commit_methods
[] = {
184 {"message", (PyCFunction
) commit_message
, METH_VARARGS
, cmessage_doc
},
185 {"id", (PyCFunction
) commit_id
, METH_VARARGS
, commit_id_doc
},
186 {"tree", (PyCFunction
) commit_tree
, METH_VARARGS
, commit_tree_doc
},
187 {"buffer", (PyCFunction
) commit_raw
, METH_VARARGS
, commit_raw_doc
},
188 {"committer_email", (PyCFunction
) commit_committer_email
,
189 METH_VARARGS
, ccommitter_email_doc
},
190 {"committer_name", (PyCFunction
) commit_committer_name
, METH_VARARGS
,
191 ccommitter_name_doc
},
192 {"author_email", (PyCFunction
) commit_author_email
, METH_VARARGS
,
194 {"author_name", (PyCFunction
) commit_author_name
, METH_VARARGS
,
196 {NULL
, NULL
, 0, NULL
}
200 commit_dealloc(GitCommitObject
*self
)
202 git_commit_free(self
->commit
);
203 self
->ob_type
->tp_free((PyObject
*) self
);
207 commit_compare(GitCommitObject
*a
, GitCommitObject
*b
)
210 time_t a_time
, b_time
;
212 if (git_commit_equal(a
->commit
, b
->commit
))
215 ret
= git_commit_committer_date(a
->commit
, &a_time
, &a_tz
);
221 ret
= git_commit_committer_date(b
->commit
, &b_time
, &b_tz
);
228 * FIXME: We should convert to UTC and then compare, but
229 * this is incomplete for now...
232 PyErr_SetString(PyGitError
, "time zone must be equal");
236 ret
= a_time
< b_time
? -1 : 1;
240 static PyTypeObject Git_Commit_Type
= {
241 PyObject_HEAD_INIT(NULL
)
243 "pygit.comit", /* tp_name */
244 sizeof(GitCommitObject
), /* tp_basicsize */
246 (destructor
)commit_dealloc
, /* tp_dealloc */
250 (cmpfunc
)commit_compare
, /* tp_compare */
252 0, /* tp_as_number */
253 0, /* tp_as_sequence */
254 0, /* tp_as_mapping */
260 0, /* tp_as_buffer */
261 Py_TPFLAGS_DEFAULT
, /* tp_flags */
265 0, /* tp_richcompare */
266 0, /* tp_weaklistoffset */
269 commit_methods
, /* tp_methods */
274 0, /* tp_descr_get */
275 0, /* tp_descr_set */
276 0, /* tp_dictoffset */
288 struct git_revlist_opt
*opt
;
292 revlist_add_commit(GitRevListObject
*self
, PyObject
*args
, int exclude
)
295 unsigned char sha1
[GIT_SHA1_SIZE
];
297 err
= pyarg_to_sha1(args
, sha1
);
299 return pygit_error();
302 err
= git_revlist_exclude(self
->opt
, sha1
);
304 err
= git_revlist_include(self
->opt
, sha1
);
307 return pygit_error();
313 revlist_include(GitRevListObject
*self
, PyObject
*args
)
315 return revlist_add_commit(self
, args
, 0);
319 revlist_exclude(GitRevListObject
*self
, PyObject
*args
)
321 return revlist_add_commit(self
, args
, 1);
325 revlist_reverse(GitRevListObject
*self
, PyObject
*args
)
331 err
= git_revlist_reverse(self
->opt
);
333 return pygit_error();
339 revlist_show_merges(GitRevListObject
*self
, PyObject
*args
)
345 err
= git_revlist_show_merges(self
->opt
);
347 return pygit_error();
353 revlist_max_count(GitRevListObject
*self
, PyObject
*args
)
358 if (!PyArg_ParseTuple(args
, "k", &count
))
361 err
= git_revlist_max_count(self
->opt
, (size_t) count
);
363 return pygit_error();
368 static PyMethodDef revlist_methods
[] = {
369 {"include", (PyCFunction
) revlist_include
, METH_VARARGS
, NULL
},
370 {"exclude", (PyCFunction
) revlist_exclude
, METH_VARARGS
, NULL
},
371 {"reverse", (PyCFunction
) revlist_reverse
, METH_NOARGS
, NULL
},
372 {"show_merges", (PyCFunction
) revlist_show_merges
, METH_NOARGS
, NULL
},
373 {"max_count", (PyCFunction
) revlist_max_count
,METH_VARARGS
,NULL
},
374 {NULL
, NULL
, 0, NULL
}
378 revlist_dealloc(GitRevListObject
*self
)
380 git_revlist_free(self
->opt
);
381 self
->ob_type
->tp_free((PyObject
*) self
);
385 revlist_iter(GitRevListObject
*self
)
388 return (PyObject
*) self
;
392 revlist_iternext(GitRevListObject
*self
)
396 struct git_commit
*commit
;
398 m
= PyObject_New(GitCommitObject
, &Git_Commit_Type
);
402 ret
= PyType_Ready(&Git_Commit_Type
);
408 commit
= git_commit_init();
411 return pygit_error();
414 ret
= git_revlist_next(self
->opt
, commit
);
416 git_commit_free(commit
);
422 return (PyObject
*) m
;
425 static PyTypeObject Git_RevList_Type
= {
426 PyObject_HEAD_INIT(NULL
)
428 "pygit.revlist", /* tp_name */
429 sizeof(GitRevListObject
), /* tp_basicsize */
431 (destructor
)revlist_dealloc
, /* tp_dealloc */
437 0, /* tp_as_number */
438 0, /* tp_as_sequence */
439 0, /* tp_as_mapping */
445 0, /* tp_as_buffer */
446 Py_TPFLAGS_DEFAULT
, /* tp_flags */
450 0, /* tp_richcompare */
451 0, /* tp_weaklistoffset */
452 (getiterfunc
)revlist_iter
, /* tp_iter */
453 (iternextfunc
)revlist_iternext
, /* tp_iternext */
454 revlist_methods
, /* tp_methods */
459 0, /* tp_descr_get */
460 0, /* tp_descr_set */
461 0, /* tp_dictoffset */
477 repo_read_obj(PyObject
*args
,
478 int (*read_obj
)(unsigned char *sha1
, void **buf
, size_t *len
))
483 unsigned char sha1
[GIT_SHA1_SIZE
];
485 err
= pyarg_to_sha1(args
, sha1
);
489 err
= read_obj(sha1
, &buf
, NULL
);
491 return pygit_error();
493 ret
= PyString_FromString((char *) buf
);
500 repo_head_commit(GitRepoObject
*self
, PyObject
*args
)
503 unsigned char sha1
[GIT_SHA1_SIZE
];
508 err
= git_repo_head(sha1
);
510 return pygit_error();
512 return sha1_to_pystr(sha1
);
516 repo_read_commit(GitRepoObject
*self
, PyObject
*args
)
519 return repo_read_obj(args
, git_repo_commit_read
);
523 repo_read_blob(GitRepoObject
*self
, PyObject
*args
)
526 return repo_read_obj(args
, git_repo_blob_read
);
530 repo_lookup_commit(GitRepoObject
*self
, PyObject
*args
)
534 struct git_commit
*commit
;
535 unsigned char sha1
[GIT_SHA1_SIZE
];
539 err
= pyarg_to_sha1(args
, sha1
);
543 m
= PyObject_New(GitCommitObject
, &Git_Commit_Type
);
547 err
= PyType_Ready(&Git_Commit_Type
);
553 commit
= git_commit_lookup(sha1
);
556 return pygit_error();
560 return (PyObject
*) m
;
564 repo_translate_ref(GitRepoObject
*self
, PyObject
*args
)
568 unsigned char sha1
[GIT_SHA1_SIZE
];
572 if (!PyArg_ParseTuple(args
, "s", &ref
))
575 err
= git_repo_translate_ref(ref
, sha1
);
577 return pygit_error();
579 return sha1_to_pystr(sha1
);
583 repo_revlist(GitRepoObject
*self
, PyObject
*args
)
591 m
= PyObject_New(GitRevListObject
, &Git_RevList_Type
);
595 err
= PyType_Ready(&Git_RevList_Type
);
601 m
->opt
= git_revlist_init();
604 return pygit_error();
607 return (PyObject
*) m
;
610 static PyMethodDef repo_methods
[] = {
611 {"read_commit", (PyCFunction
) repo_read_commit
, METH_VARARGS
, NULL
},
612 {"read_blob", (PyCFunction
) repo_read_blob
, METH_VARARGS
, NULL
},
613 {"lookup_commit", (PyCFunction
) repo_lookup_commit
, METH_VARARGS
,NULL
},
614 {"head_commit", (PyCFunction
) repo_head_commit
, METH_NOARGS
, NULL
},
615 {"translate_ref", (PyCFunction
) repo_translate_ref
,METH_VARARGS
, NULL
},
616 {"revlist", (PyCFunction
) repo_revlist
, METH_VARARGS
, NULL
},
617 {NULL
, NULL
, 0, NULL
}
620 static PyMemberDef repo_members
[] = {
621 {"path", T_OBJECT_EX
, offsetof(GitRepoObject
, path
), 0,
622 "repository's path"},
623 {NULL
, 0, 0, 0, NULL
}
627 repo_dealloc(GitRepoObject
*self
)
629 Py_DECREF(self
->path
);
630 self
->ob_type
->tp_free((PyObject
*) self
);
633 static PyTypeObject Git_Repo_Type
= {
634 PyObject_HEAD_INIT(NULL
)
636 "pygit.repo", /* tp_name */
637 sizeof(GitRepoObject
), /* tp_basicsize */
639 (destructor
)repo_dealloc
, /* tp_dealloc */
645 0, /* tp_as_number */
646 0, /* tp_as_sequence */
647 0, /* tp_as_mapping */
653 0, /* tp_as_buffer */
654 Py_TPFLAGS_DEFAULT
, /* tp_flags */
658 0, /* tp_richcompare */
659 0, /* tp_weaklistoffset */
662 repo_methods
, /* tp_methods */
663 repo_members
, /* tp_members */
667 0, /* tp_descr_get */
668 0, /* tp_descr_set */
669 0, /* tp_dictoffset */
680 pygit_open(PyObject
*self
, PyObject
*args
)
688 if (!PyArg_ParseTuple(args
, "s", &dir
))
691 err
= git_repo_open(dir
);
693 return pygit_error();
695 m
= PyObject_New(GitRepoObject
, &Git_Repo_Type
);
699 err
= PyType_Ready(&Git_Repo_Type
);
705 m
->path
= PyString_FromString(dir
);
711 return (PyObject
*) m
;
714 static PyMethodDef pygit_methods
[] = {
715 { "open", pygit_open
, METH_VARARGS
, "Open a GIT repository" },
716 { NULL
, NULL
, 0, NULL
}
724 m
= Py_InitModule("pygit", pygit_methods
);
728 PyGitError
= PyErr_NewException("pygit.error", NULL
, NULL
);
732 Py_INCREF(PyGitError
);
733 PyModule_AddObject(m
, "error", PyGitError
);