Skip to content

Mention of deprecated symbols in 101 samples #110

Open

Description

@Lattay

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 ?

Activity

  1. ethomson commented on Nov 23, 2022

    @ethomson
    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 */
    }
    
  2. Lattay commented on Nov 23, 2022

    @Lattay
    ContributorAuthor

    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.

  3. Lattay commented on Nov 24, 2022

    @Lattay
    ContributorAuthor

    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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions