Search code examples
gitsshlibgit2

Create ssh based remote path


How should be set the url to add a ssh based remote path to an initialized repository? I have tried with

git_remote_create(&remote, repo, "origin", "ssh://[email protected]/libgit2/TestGitRepository");

but it does not fetch correctly and git_remote_stats returns 0 received objects. If ssh is replaced with https, git_fetch works as expected. The same url works well with git_clone(see comment):

git_clone(&repo, "ssh://[email protected]/libgit2/TestGitRepository", "foo", &clone_opts);

I have also tried to set ssh://[email protected]:libgit2/TestGitRepository, but it does not work either.


Solution

  • The problem was caused because I was not using the credential callback.

    From the callback section in the libgit2 documentation:

    For a credentials example, check out the fetch example, which uses an interactive credential callback. See also the built-in credential helpers.

    Below a minimal example to init+fetch+checkout a repo using ssh:

    #include <git2.h>
    #include <string.h>
    
    int credentials_cb(git_credential **out, const char *url, const char *username_from_url,
        unsigned int allowed_types, void *payload)
    {
      int err;
      char *username = NULL, *password = NULL, *privkey = NULL, *pubkey = NULL;
      username = strdup("git");
      password = strdup("PASSWORD");
      pubkey = strdup("/home/user/.ssh/id_rsa.pub");
      privkey = strdup("/home/user/.ssh/id_rsa");
    
      err = git_credential_ssh_key_new(out, username, pubkey, privkey, password);
    
      free(username);
      free(password);
      free(privkey);
      free(pubkey);
    
      return err;
    }
    
    int main(void)
    {
    
      git_repository *repo;
    
      git_libgit2_init();
    
      git_repository_init(&repo, "libgit2-test-ssh/", 0);
    
      git_remote *remote;
      git_remote_create(
          &remote, repo, "origin",
          "ssh://[email protected]/libgit2/TestGitRepository");
    
      git_fetch_options fetch_opts = GIT_FETCH_OPTIONS_INIT;
      fetch_opts.callbacks.credentials = credentials_cb;
      git_remote_fetch(remote, NULL, &fetch_opts, NULL);
    
      git_object *branch;
      git_revparse_single(&branch, repo, "remotes/origin/master");
      git_checkout_options checkout_opts = GIT_CHECKOUT_OPTIONS_INIT;
      git_checkout_tree(repo, branch, &checkout_opts);
    
      git_object_free(branch);
      git_remote_free(remote);
    
      git_repository_free(repo);
      git_libgit2_shutdown();
    
      return 0;
    }