克隆一个git repo(深入)

时间:2012-05-17 19:57:31

标签: objective-c c git git-clone

如何克隆回购(使用libgit2

我想与git clonelibgit2完全相同的事情。我可能会问的是git clone究竟做了什么。

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

  1. 初始化回购
  2. 调整配置文件以添加远程
  3. 创建git_remote
  4. 下载packfile
  5. 索引packfile并编写索引(给我们一个.idx文件)
  6. (编辑)将所有不同的分支写入磁盘。
  7. (编辑)以某种方式做git checkout
  8. 现在我不知道该怎么做。我唯一的猜测就是将.idx加载到git_index并使用git_repository_set_index,但这也没有显示任何文件。

    修改

    我测试了在半克隆的回购邮件上运行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];
    
    }
    

1 个答案:

答案 0 :(得分:4)

由于libgit2在其explicitly mention git clone中没有issue list,因此在原始git项目的源代码中会有以下内容:

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