status 这个操作是干啥的就不细解释了,这个不知道的话是不太适合看这套教程的,先去补补 git 相关的知识。这集的代码写起来还比较简单,在开动之前先复习一下基础概念。
HEAD、index、workdir:
HEAD 是当前所在的分支的最后一次 commit ,重点是已经 commit 了的状态。
index 是 git_index_add 之后的状态。但是要注意一下,这指的并不一定是使用命令行的 git add 命令完成。仅仅是加到 index 中就算了,并不需要完成 git_index_write 把内存中的状态写入磁盘。
workdir 还没加到 index 之前的都算在 workdir 的状态。
libgit 实现 status 大体上有两个方案,一个是简单一些,可以得到的信息也相对比较少的;另一个可以获得更详细的信息。我们从简单的开始
1. 简单方案
1 2 3 4 5 6 7 |
int status_cb(const char *path, unsigned int status_flags, void *payload) { std::cout << "path: " << path; std::cout << "\nflag: " << status_flags << std::endl; return 0; } |
1 |
error = git_status_foreach(rep, status_cb, nullptr); |
通过 callback 获取状态信息,
path 文件的相对路径
status_flags 是状态的枚举值
payload 是一个透传参数,从 git_status_foreach 第三个参数原样传入
关于状态的枚举值,这个枚举的声明是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
/** * Status flags for a single file. * * A combination of these values will be returned to indicate the status of * a file. Status compares the working directory, the index, and the * current HEAD of the repository. The `GIT_STATUS_INDEX` set of flags * represents the status of file in the index relative to the HEAD, and the * `GIT_STATUS_WT` set of flags represent the status of the file in the * working directory relative to the index. */ typedef enum { GIT_STATUS_CURRENT = 0, GIT_STATUS_INDEX_NEW = (1u << 0), GIT_STATUS_INDEX_MODIFIED = (1u << 1), GIT_STATUS_INDEX_DELETED = (1u << 2), GIT_STATUS_INDEX_RENAMED = (1u << 3), GIT_STATUS_INDEX_TYPECHANGE = (1u << 4), GIT_STATUS_WT_NEW = (1u << 7), GIT_STATUS_WT_MODIFIED = (1u << 8), GIT_STATUS_WT_DELETED = (1u << 9), GIT_STATUS_WT_TYPECHANGE = (1u << 10), GIT_STATUS_WT_RENAMED = (1u << 11), GIT_STATUS_WT_UNREADABLE = (1u << 12), GIT_STATUS_IGNORED = (1u << 14), GIT_STATUS_CONFLICTED = (1u << 15), } git_status_t; |
IGNORED 是被忽略的文件,表示这个文件满足 .gitignore 中的规则。
CONFLICTED 是合并之后有冲突的文件。
GIT_STATUS_INDEX 开头的是 index 相对于 HEAD 的状态。
GIT_STATUS_WT 开头的是 workdir 相对于 index 的状态。
2. 详细方案
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
git_status_options opt = GIT_STATUS_OPTIONS_INIT; git_status_list* statuses = nullptr; size_t count = 0; opt.flags = GIT_STATUS_OPT_DEFAULTS; error = git_status_list_new(&statuses, rep, &opt); count = git_status_list_entrycount(statuses); std::cout<< "count: " << count << std::endl; for (size_t i = 0; i < count; ++i) { const git_status_entry* entry = git_status_byindex(statuses, i); std::cout<<"status: " << entry->index_to_workdir->status << "\tpath: " << entry->index_to_workdir->new_file.path << std::endl; } git_status_list_free(statuses); |
1) 初始化选项
2) 获取 git_status_list
3) 遍历 list 取出 git_status_entry
1 2 3 4 5 |
typedef struct { git_status_t status; git_diff_delta *head_to_index; git_diff_delta *index_to_workdir; } git_status_entry; |
git_status_entry 除了有文件状态的标示,还带有 diff 的详细信息,而且严格区分了 HEAD 相对 index ,和 index 相对 workdir。
关于 diff 有很多要详细解释的东西,就放到下回了,我得花点时间读注释去了……