From 0bbd15b4f1412a8d08fadc3e06c0384c5c1bf1ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carlos=20Mart=C3=ADn=20Nieto?= Date: Sat, 25 Jan 2014 10:20:31 +0100 Subject: [PATCH] TransferProgress: create this type for transfer progress reporting This gets passed to the transfer progress callback, instead of the stripped-down version which Remote.fetch() returns. --- docs/remotes.rst | 14 +++++++ src/pygit2.c | 5 ++- src/remote.c | 95 ++++++++++++++++++++++++++++++++++++++++++++---- src/types.h | 12 ++++++ src/utils.h | 3 ++ 5 files changed, 120 insertions(+), 9 deletions(-) diff --git a/docs/remotes.rst b/docs/remotes.rst index b136fee..e7c5129 100644 --- a/docs/remotes.rst +++ b/docs/remotes.rst @@ -28,6 +28,20 @@ The Remote type .. automethod:: pygit2.Remote.push .. automethod:: pygit2.Remote.save +The TransferProgress type +=========================== + +This class contains the data which is available to us during a fetch. + +.. autoattribute:: pygit2.TransferProgress.total_objects +.. autoattribute:: pygit2.TransferProgress.indexed_objects +.. autoattribute:: pygit2.TransferProgress.received_objects +.. autoattribute:: pygit2.TransferProgress.local_objects +.. autoattribute:: pygit2.TransferProgress.total_deltas +.. autoattribute:: pygit2.TransferProgress.indexed_deltas +.. autoattribute:: pygit2.TransferProgress.received_bytes + + The Refspec type =================== diff --git a/src/pygit2.c b/src/pygit2.c index 7c72e50..e324a64 100644 --- a/src/pygit2.c +++ b/src/pygit2.c @@ -64,6 +64,7 @@ extern PyTypeObject BranchType; extern PyTypeObject SignatureType; extern PyTypeObject RemoteType; extern PyTypeObject RefspecType; +extern PyTypeObject TransferProgressType; extern PyTypeObject NoteType; extern PyTypeObject NoteIterType; extern PyTypeObject BlameType; @@ -420,9 +421,11 @@ moduleinit(PyObject* m) /* Remotes */ INIT_TYPE(RemoteType, NULL, NULL) - ADD_TYPE(m, Remote) INIT_TYPE(RefspecType, NULL, NULL) + INIT_TYPE(TransferProgressType, NULL, NULL) + ADD_TYPE(m, Remote) ADD_TYPE(m, Refspec) + ADD_TYPE(m, TransferProgress) /* Direction for the refspec */ ADD_CONSTANT_INT(m, GIT_DIRECTION_FETCH) ADD_CONSTANT_INT(m, GIT_DIRECTION_PUSH) diff --git a/src/remote.c b/src/remote.c index 1b82586..3ee0ab7 100644 --- a/src/remote.c +++ b/src/remote.c @@ -38,6 +38,7 @@ extern PyObject *GitError; extern PyTypeObject RepositoryType; extern PyTypeObject RefspecType; +extern PyTypeObject TransferProgressType; Refspec * wrap_refspec(const Remote *owner, const git_refspec *refspec) @@ -295,6 +296,87 @@ PyTypeObject RefspecType = { 0, /* tp_new */ }; +PyObject * +wrap_transfer_progress(const git_transfer_progress *stats) +{ + TransferProgress *py_stats; + + py_stats = PyObject_New(TransferProgress, &TransferProgressType); + if (!py_stats) + return NULL; + + py_stats->total_objects = stats->total_objects; + py_stats->indexed_objects = stats->indexed_objects; + py_stats->received_objects = stats->received_objects; + py_stats->local_objects = stats->local_objects; + py_stats->total_deltas = stats->total_deltas; + py_stats->indexed_deltas = stats->indexed_deltas; + py_stats->received_bytes = stats->received_bytes; + + return (PyObject *) py_stats; +} + +void +TransferProgress_dealloc(TransferProgress *self) +{ + PyObject_Del(self); +} + +PyMemberDef TransferProgress_members[] = { + RMEMBER(TransferProgress, total_objects, T_UINT, "Total number objects to download"), + RMEMBER(TransferProgress, indexed_objects, T_UINT, "Objects which have been indexed"), + RMEMBER(TransferProgress, received_objects, T_UINT, "Objects which have been received up to now"), + RMEMBER(TransferProgress, local_objects, T_UINT, "Local objects which were used to fix the thin pack"), + RMEMBER(TransferProgress, total_deltas, T_UINT, "Total number of deltas in the pack"), + RMEMBER(TransferProgress, indexed_deltas, T_UINT, "Deltas which have been indexed"), + /* FIXME: technically this is unsigned, but there's no value for size_t here. */ + RMEMBER(TransferProgress, received_bytes, T_PYSSIZET, "Number of bytes received up to now"), + {NULL}, +}; + +PyDoc_STRVAR(TransferProgress__doc__, "Progress downloading and indexing data during a fetch"); + +PyTypeObject TransferProgressType = { + PyVarObject_HEAD_INIT(NULL, 0) + "_pygit2.TransferProgress", /* tp_name */ + sizeof(TransferProgress), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)TransferProgress_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + TransferProgress__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + TransferProgress_members, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ +}; + static int progress_cb(const char *str, int len, void *data) { @@ -325,7 +407,7 @@ static int transfer_progress_cb(const git_transfer_progress *stats, void *data) { Remote *remote = (Remote *) data; - PyObject *arglist, *ret; + PyObject *py_stats, *ret; if (remote->transfer_progress == NULL) return 0; @@ -335,14 +417,11 @@ transfer_progress_cb(const git_transfer_progress *stats, void *data) return -1; } - arglist = Py_BuildValue("({s:I,s:I,s:n})", - "indexed_objects", stats->indexed_objects, - "received_objects", stats->received_objects, - "received_bytes", stats->received_bytes); - - ret = PyObject_CallObject(remote->transfer_progress, arglist); - Py_DECREF(arglist); + py_stats = wrap_transfer_progress(stats); + if (!py_stats) + return -1; + ret = PyObject_CallFunctionObjArgs(remote->transfer_progress, py_stats, NULL); if (!ret) return -1; diff --git a/src/types.h b/src/types.h index c8f7a6f..95d2bd2 100644 --- a/src/types.h +++ b/src/types.h @@ -213,6 +213,18 @@ typedef struct { const git_refspec *refspec; } Refspec; +/* git_transfer_progress */ +typedef struct { + PyObject_HEAD + unsigned int total_objects; + unsigned int indexed_objects; + unsigned int received_objects; + unsigned int local_objects; + unsigned int total_deltas; + unsigned int indexed_deltas; + size_t received_bytes; +} TransferProgress; + /* git_blame */ SIMPLE_TYPE(Blame, git_blame, blame) diff --git a/src/utils.h b/src/utils.h index 62699e8..66d9234 100644 --- a/src/utils.h +++ b/src/utils.h @@ -133,6 +133,9 @@ char * py_str_to_c_str(PyObject *value, const char *encoding); #define MEMBER(type, attr, attr_type, docstr)\ {#attr, attr_type, offsetof(type, attr), 0, PyDoc_STR(docstr)} +#define RMEMBER(type, attr, attr_type, docstr)\ + {#attr, attr_type, offsetof(type, attr), READONLY, PyDoc_STR(docstr)} + /* Helpers for memory allocation */ #define CALLOC(ptr, num, size, label) \