Mention of deprecated symbols in 101 samples
Hello,
I am starting to learn the libgit2 API and in the first example I wanted to try I stumbled upon git_indexer_progress: https://libgit2.org/docs/guides/101-samples/#repositories_clone_progress.
Unfortunately, this does not appear anywhere in the reference: https://libgit2.org/libgit2/#HEAD/search/git_transfer_progress.
Further investigation showed that it is simply because it is a deprecated name of git_indexer_progress.
So, I will definitely do a PR for this particular instance, but it would be nice to be able to catch all such symbols automatically if possible.
Do you think there would be a reliable way to do so, or we should try to parse the "deprecated" header ?
Very good question. It wonder if we can do something clever here that fixes two problems:
- These are text docs / markdown and so easy to get out of sync with our code or best practices. We don't break APIs very often -- but we will in a SHA256 compatible world. 😱
- Our "examples" are a poor attempt at a git cli implementation.
I can imagine a world where our examples are smaller pieces of code -- or that we pull the samples data out of the examples code itself. We probably wouldn't want all the boilerplate, so you can imagine something like:
#include "git2.h"
int main(int argc, char **argv)
{
/** sample start: clone (progress) */
progress_data d = {0};
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
clone_opts.checkout_opts.progress_cb = checkout_progress;
clone_opts.checkout_opts.progress_payload = &d;
clone_opts.fetch_opts.callbacks.transfer_progress = fetch_progress;
clone_opts.fetch_opts.callbacks.payload = &d;
git_repository *repo = NULL;
int error = git_clone(&repo, url, path, &clone_opts);
/** sample end */
}
If all the example were easily compilable (modulo a bit of boiler plate) it would be pretty easy to programmatically check that deprecated symbols are removed.
It would be sufficient to #define GIT_DEPRECATE_HARD and have them all compiled in the testing pipeline.
I believe there is some ad-hoc literate programming stuff that want to emerge from this problem :stuck_out_tongue:. I may look into it later this week if I have some time.
I had time earlier than expected, so I tinkered yesterday with a bit of python, and I think I am on the right track. Currently, I have a script that cut the existing index into independent files, and another one that seem back the files into a single markdown file. A third script converts the individual markdown files into C files and try to compile them. The current state of the examples doesn't make this approach viable yet because it is basically impossible to parse a C snippet where the main function is implicit, but with some well-placed markings there should be no problem.
As an example, one file may be something like that:
One can track the progress of the clone operation thanks to a callback.
~~~c
typedef struct { /* … */ } progress_data;
int fetch_progress(
const git_indexer_progress *stats,
void *payload)
{
progress_data *pd = (progress_data*)payload;
/* Do something with network transfer progress */
}
void checkout_progress(
const char *path,
size_t cur,
size_t tot,
void *payload)
{
progress_data *pd = (progress_data*)payload;
/* Do something with checkout progress */
}
// !BEGIN_MAIN
progress_data d = {0};
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
char *url = "https://github.com/libgit2/libgit2";
char *path = "libgit2";
clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
clone_opts.checkout_opts.progress_cb = checkout_progress;
clone_opts.checkout_opts.progress_payload = &d;
clone_opts.fetch_opts.callbacks.transfer_progress = fetch_progress;
clone_opts.fetch_opts.callbacks.payload = &d;
git_repository *repo = NULL;
int error = git_clone(&repo, url, path, &clone_opts);
~~~
([`git_clone`](http://libgit2.org/libgit2/#HEAD/group/clone/git_clone),
[`git_clone_options`](http://libgit2.org/libgit2/#HEAD/type/git_clone_options))
Which would either be pasted mostly as-is in the index.md (without the !BEGIN_MAIN mark, or maybe replacing it with a more human friendly comment) and would produce a C program like that:
/*
* Repositories
* Clone (Progress)
* This file is automatically generated for testing purpose.
*/
#define GIT_DEPRECATE_HARD
#include <git2.h>
/* One can track the progress of the clone operation thanks to a callback. */
typedef struct { /* … */ } progress_data;
int fetch_progress(
const git_indexer_progress *stats,
void *payload)
{
progress_data *pd = (progress_data*)payload;
/* Do something with network transfer progress */
}
void checkout_progress(
const char *path,
size_t cur,
size_t tot,
void *payload)
{
progress_data *pd = (progress_data*)payload;
/* Do something with checkout progress */
}
int main()
{
git_libgit2_init();
progress_data d = {0};
git_clone_options clone_opts = GIT_CLONE_OPTIONS_INIT;
char *url = "https://github.com/libgit2/libgit2";
char *path = "libgit2";
clone_opts.checkout_opts.checkout_strategy = GIT_CHECKOUT_SAFE;
clone_opts.checkout_opts.progress_cb = checkout_progress;
clone_opts.checkout_opts.progress_payload = &d;
clone_opts.fetch_opts.callbacks.transfer_progress = fetch_progress;
clone_opts.fetch_opts.callbacks.payload = &d;
git_repository *repo = NULL;
int error = git_clone(&repo, url, path, &clone_opts);
return 0;
}
/*
* ([`git_clone`](http://libgit2.org/libgit2/#HEAD/group/clone/git_clone),
* [`git_clone_options`](http://libgit2.org/libgit2/#HEAD/type/git_clone_options))
*/
Do you think this would be an acceptable solution for this project? If so, would you be OK with python scripts? Alternatively, I can port them to ruby since Jekyll already require that.