libgit2使用教程(四) git status

status 这个操作是干啥的就不细解释了,这个不知道的话是不太适合看这套教程的,先去补补 git 相关的知识。这集的代码写起来还比较简单,在开动之前先复习一下基础概念。
HEAD、index、workdir:
HEAD 是当前所在的分支的最后一次 commit ,重点是已经 commit 了的状态。
index 是 git_index_add 之后的状态。但是要注意一下,这指的并不一定是使用命令行的 git add 命令完成。仅仅是加到 index 中就算了,并不需要完成 git_index_write 把内存中的状态写入磁盘。
workdir 还没加到 index 之前的都算在 workdir 的状态。

libgit 实现 status 大体上有两个方案,一个是简单一些,可以得到的信息也相对比较少的;另一个可以获得更详细的信息。我们从简单的开始

1. 简单方案

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;
}
error = git_status_foreach(rep, status_cb, nullptr);

通过 callback 获取状态信息,
path 文件的相对路径
status_flags 是状态的枚举值
payload 是一个透传参数,从 git_status_foreach 第三个参数原样传入

关于状态的枚举值,这个枚举的声明是这样的:

/**
 * 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. 详细方案

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

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 有很多要详细解释的东西,就放到下回了,我得花点时间读注释去了……

《libgit2使用教程(四) git status》有一个想法

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

RSS
Follow by Email
YouTube
YouTube
Pinterest
fb-share-icon
LinkedIn
Share
VK
Weibo
WeChat
WhatsApp
Reddit
FbMessenger
Copy link
URL has been copied successfully!