libgit2不会获取更改,但始终是一切

aus*_*aus 2 libgit2

我正在尝试使用libgit2来首先克隆一个裸存储库,然后使用来自github源的更改来更新它.克隆工作正常:

git_repository *_repository
git_clone_bare(&_repository, REPOSITORY_URL, path, &transferProgressCallback, NULL);
git_repository_free(_repository);
Run Code Online (Sandbox Code Playgroud)

但是当我尝试从源libgit2更新存储库时,总是再次下载整个存储库.它只是不提取更改.我正在使用此代码:

git_remote *remote;
git_repository *_repository;

git_repository_open(&_repository, path);
git_remote_load(&remote, _repository, "origin");
git_remote_connect(remote, GIT_DIR_FETCH);
git_remote_download(remote, &transferProgressCallback, NULL);

git_remote_disconnect(remote);
git_remote_update_tips(remote);
git_remote_free(remote);
Run Code Online (Sandbox Code Playgroud)

(我删除了错误处理.)我使用这样的回调来报告进度:

void transferProgressCallback(const git_transfer_progress *stats, void *payload) {
    float receivedMegaBytes = (float)stats->received_bytes/(1024*1024.0);
    float progress = ((float)stats->received_objects / (float)stats->total_objects) * 100.0;
    printf("Loading: %.1f (%.1f)\n", progress, receivedMegaBytes);
}
Run Code Online (Sandbox Code Playgroud)

根据回调,下载了所有内容(与git_clone_bare相同的字节数).我一定是错过了什么或做错了什么,对吧?但我没有看到哪里.我想要的只是代码仅提取更改(即本地不存在的内容).但相反,它不断获取整个存储库.

拜托,这可能是什么问题?非常感谢你提前!

nul*_*ken 6

奇怪.我无法重现这个问题.

您正在运行哪个版本的libgit2?

我已经在本地添加了一个测试到libgit2 fetch套件,它可以重现你的问题,并且...它会反对当前最新的libgit2开发技巧.成功检查了以下网址:

static void transferProgressCallback(const git_transfer_progress *stats, void *payload)
{
    bool *invoked = (bool *)payload;
    *invoked = true;
}

void test_network_fetch__doesnt_retreive_a_pack_when_the_repository_is_up_to_date(void)
{
    git_repository *_repository;
    git_remote *remote;
    bool invoked = false;

    cl_git_pass(git_clone_bare(&_repository, "https://github.com/libgit2/TestGitRepository.git", "./fetch/lg2", NULL, NULL));
    git_repository_free(_repository);

    cl_git_pass(git_repository_open(&_repository, "./fetch/lg2"));

    cl_git_pass(git_remote_load(&remote, _repository, "origin"));
    cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH));

    cl_assert_equal_i(false, invoked);

    cl_git_pass(git_remote_download(remote, &transferProgressCallback, &invoked));

    cl_assert_equal_i(false, invoked);

    cl_git_pass(git_remote_update_tips(remote));
    git_remote_disconnect(remote);

    git_remote_free(remote);
    git_repository_free(_repository);
}
Run Code Online (Sandbox Code Playgroud)

更新:

我已经向libgit2项目发送了一个pull请求,以确保测试也传递给CI服务器Travis.

更新2:

好的,我已经做了一些更多的故障排除,我仍然无法重现这个问题.

  • 我通过Web界面在GitHub上创建了一个新的存储库
  • 通过bash会话,我创建了一个提交,然后将其推送到上游
  • 然后我通过libgit2在一个新的临时文件夹中克隆它.下载了3个对象
  • 然后我再次取出它,没有下载任何内容.
  • 回到bash会话,我创建了另一个提交并将其推送到上游
  • 回到libgit2代码,再次获取从第二次提交中下载3个新对象.

下面的代码,即使这不是一个真正的测试(因为它需要用户的一些交互),演示了上面解释的内容.

void test_network_fetch__retrieve_a_pack_when_the_remote_repository_has_been_updated(void)
{
    git_repository *_repository;
    git_remote *remote;
    bool invoked = false;

    /*
     * $ mkdir /tmp/so-check/ && cd /tmp/so-check/
     * 
     * $ touch README.md
     * 
     * $ git init
     * Initialized empty Git repository in d:/temp/so-check/.git/
     * 
     * $ git add README.md
     * 
     * $ git commit -m "first commit"
     * [master (root-commit) e3454be] first commit
     *  0 files changed
     *  create mode 100644 README.md
     * 
     * $ git remote add origin https://github.com/nulltoken/so-check.git
     * 
     * $ git push -u origin master
     * Username for 'https://github.com': nulltoken
     * Password for 'https://nulltoken@github.com':
     * Counting objects: 3, done.
     * Writing objects: 100% (3/3), 212 bytes, done.
     * Total 3 (delta 0), reused 0 (delta 0)
     * To https://github.com/nulltoken/so-check.git
     *  * [new branch]      master -> master
     * Branch master set up to track remote branch master from origin.
     * 
     * $
     */

    cl_git_pass(git_clone_bare(&_repository, "https://github.com/nulltoken/so-check.git", "./fetch/soc", NULL, NULL));
    git_repository_free(_repository);

    cl_git_pass(git_repository_open(&_repository, "./fetch/soc"));

    cl_git_pass(git_remote_load(&remote, _repository, "origin"));
    cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH));

    cl_assert_equal_i(false, invoked);

    cl_git_pass(git_remote_download(remote, &transferProgressCallback, &invoked));

    cl_assert_equal_i(false, invoked);

    cl_git_pass(git_remote_update_tips(remote));
    git_remote_disconnect(remote);

    git_remote_free(remote);
    git_repository_free(_repository);

    /*
     * $ mkdir /tmp/so-check2 && cd /tmp/so-check2
     * 
     * $ git clone https://github.com/nulltoken/so-check.git .
     * Cloning into '.'...
     * remote: Counting objects: 3, done.
     * remote: Total 3 (delta 0), reused 3 (delta 0)
     * Unpacking objects: 100% (3/3), done.
     *
     * $ echo "Test" > README.md
     * 
     * $ git add README.md
     * 
     * $ git commit -m "Now with a meaningful content"
     * [master 9c6c300] Now with a meaningful content
     *  1 file changed, 1 insertion(+)
     *
     $ git push
     * Username for 'https://github.com': nulltoken
     * Password for 'https://nulltoken@github.com':
     * Counting objects: 5, done.
     * Writing objects: 100% (3/3), 262 bytes, done.
     * Total 3 (delta 0), reused 0 (delta 0)
     * To https://github.com/nulltoken/so-check.git
     *    e3454be..9794f71  master -> master
     * $
     */

    /* Set a breakpoint below in order to push the additional commit.
     * Once it's done, let the code run again.
     */
    cl_git_pass(git_repository_open(&_repository, "./fetch/soc"));

    cl_git_pass(git_remote_load(&remote, _repository, "origin"));
    cl_git_pass(git_remote_connect(remote, GIT_DIR_FETCH));

    cl_assert_equal_i(false, invoked);

    cl_git_pass(git_remote_download(remote, &transferProgressCallback, &invoked));

    cl_assert_equal_i(true, invoked);

    cl_git_pass(git_remote_update_tips(remote));
    git_remote_disconnect(remote);

    git_remote_free(remote);
    git_repository_free(_repository);
}
Run Code Online (Sandbox Code Playgroud)

在控制台的输出下方,导致第二次下载.可以注意到只检索到3个对象:

Fetching: (0/3)
Fetching: (1/3)
Fetching: (2/3)
Fetching: (3/3)
Fetching: (3/3)
Run Code Online (Sandbox Code Playgroud)

存储库包含6个对象(第一次提交3次,第二次提交3次):

$ git count-objects --verbose
count: 6
size: 0
in-pack: 0
packs: 0
size-pack: 0
prune-packable: 0
garbage: 0
Run Code Online (Sandbox Code Playgroud)

从我的角度来看,看起来libgit2确实能够下载差分包.

  • 哇,这是一个很棒的答案。非常感谢!所以我的 API 使用是正确的,libgit2 也能正常工作。这确实有帮助,因为我现在知道问题应该在其他地方。再次,谢谢你! (2认同)