Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mention of deprecated symbols in 101 samples #110

Open
Lattay opened this issue Nov 22, 2022 · 3 comments
Open

Mention of deprecated symbols in 101 samples #110

Lattay opened this issue Nov 22, 2022 · 3 comments

Comments

@Lattay
Copy link
Contributor

Lattay commented Nov 22, 2022

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 ?

@ethomson
Copy link
Member

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 */
}

@Lattay
Copy link
Contributor Author

Lattay commented Nov 23, 2022

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 😛.
I may look into it later this week if I have some time.

@Lattay
Copy link
Contributor Author

Lattay commented Nov 24, 2022

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants