克隆一个git repo(深入)

如何克隆repo(使用libgit2 )

我想用libgit2 git clonefunction。 我可能会问的是git clone真正深入了解了什么。

这就是我到目前为止所做的事情:

  1. 初始化回购
  2. 调整配置文件以添加远程
  3. 创建一个git_remote
  4. 下载packfile
  5. 索引packfile并编写索引(给我们一个.idx文件)
  6. (编辑)将所有不同的分支写入磁盘。
  7. (编辑)以某种方式进行git checkout

现在我不知道该怎么做。 我唯一的猜测是将.idx加载到git_index并使用git_repository_set_index ,但是它也没有显示任何文件。

编辑

我在半克隆​​的repo上测试了运行git checkout master ,这就完成了工作。 现在我只需要了解如何使用libgit2进行操作,似乎问题跟踪器中有一些有用的信息。

编辑2

我现在将添加我当前的代码,希望有一天有人能发现它有用,希望能成为我从未找到的快速启动代码。 注意:我在这里使用的是Obj-CObjective-Git ,但它主要是简单的c。

 + (GTRepository *)cloneFromRemoteURL:(NSURL *)remoteURL toLocalURL:(NSURL *)localURL { // Let's suppose the URL looks like: https://github.com/libgit2/libgit2.git // Then we need to get a URL like this too: git://github.com/libgit2/libgit2.git // This may be a bit dodgy, but it will do for now. const char *gitURL = [remoteURL.absoluteString stringByReplacingOccurrencesOfString:@"https://github.com/" withString:@"git://github.com/"].UTF8String; //Setup int error; git_repository *repo git_config *cfg; git_remote *remote; NSURL *gitDirURL = [localURL URLByAppendingPathComponent:@".git"]; error = git_repository_open(&repo, gitDirURL.path.UTF8String); if (error != GIT_SUCCESS) { git_repository_init(&repo, gitDirURL.path.UTF8String, 1); //Config git_repository_config(&cfg, repo); git_config_set_int32 (cfg, "core.repositoryformatversion", 0); git_config_set_bool (cfg, "core.filemode", 1); git_config_set_bool (cfg, "core.bare", 0); git_config_set_bool (cfg, "core.logallrefupdates", 1); git_config_set_bool (cfg, "core.ignorecase", 1); git_config_set_string (cfg, "remote.origin.url", gitURL); git_config_set_string (cfg, "remote.origin.fetch", "+refs/heads/*:refs/remotes/origin/*"); git_config_set_string (cfg, "branch.master.remote", "origin"); git_config_set_string (cfg, "branch.master.merge", "refs/heads/master"); git_repository_set_workdir(repo, localURL.path.UTF8String); error = git_remote_new(&remote, repo, "A remote", gitURL, "origin"); git_repository_free(repo); git_repository_open (&repo, localURL.path.UTF8String); } git_repository_config(&cfg, repo); // connect to repo error = git_remote_load(&remote, repo, "origin"); error = git_remote_connect(remote, GIT_DIR_FETCH); // get pack file git_off_t bytes; git_indexer_stats stats; error = git_remote_download(remote, &bytes, &stats); NSURL *packFolderURL = [localURL URLByAppendingPathComponent:@".git/objects/pack"]; NSFileManager *fileManager = [NSFileManager defaultManager]; NSArray *array = [fileManager contentsOfDirectoryAtURL:packFolderURL includingPropertiesForKeys:nil options:0 error:nil]; NSLog(@"Dictionary:%@",array); NSString *result; for (NSURL *url in array) { if ([url.path rangeOfString:@".pack"].location != NSNotFound) { result = url.path; } } const char *packname = [result UTF8String]; // unpack pack file if (packname != NULL) { git_indexer *indexer; git_indexer_stats stats2; int error; char hash[GIT_OID_HEXSZ + 1] = {0}; error = git_indexer_new(&indexer, packname); error = git_indexer_run(indexer, &stats2); error = git_indexer_write(indexer); // Get the packfile's hash (which should become it's filename) git_oid_fmt(hash, git_indexer_hash(indexer)); NSString *hashStr = [NSString stringWithCString:hash encoding:NSUTF8StringEncoding]; hashStr = [NSString stringWithFormat:@"pack-%@.idx",hashStr]; const char *indexPath = [hashStr UTF8String]; puts(hash); git_index *index; git_index_open(&index, indexPath); git_index_read(index); git_repository_set_index(repo, index); git_indexer_free(indexer); git_remote_update_tips(remote, update_cb2); //No idea what it does, but it seems like it's important… It does make the branches appear in .git/refs/remotes/origin } 

//不知怎的,在这里做git checkout master

 return [GTRepository repositoryWithURL:localURL error:nil]; } 

由于libgit2没有在其问题列表中 明确提到git clone ,因此在原始git项目的源代码中有一个引导:

  • builtin/clone.c
  • contrib/examples/git-clone.sh

最后一个脚本将引导您完成git clone所有阶段。