libgit2.github.io icon indicating copy to clipboard operation
libgit2.github.io copied to clipboard

Mention of deprecated symbols in 101 samples

Open Lattay opened this issue 3 years ago • 3 comments

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 ?

Lattay avatar Nov 22 '22 16:11 Lattay

Very good question. It wonder if we can do something clever here that fixes two problems:

  1. 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. 😱
  2. 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 */
}

ethomson avatar Nov 23 '22 12:11 ethomson

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.

Lattay avatar Nov 23 '22 14:11 Lattay

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.

Lattay avatar Nov 24 '22 09:11 Lattay