libgit2 / libgit2/libgit2sharp

[RFC] Batched low level index operations

未关闭
#908 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

还没有人认领这个 Issue。

主要语言
C#
星标
3.5k
派生
925
PR 合并指标
30 天内没有已合并 PR

描述

In the light of https://github.com/libgit2/libgit2sharp/pull/907, I was wondering if we should take this approach one step further.

Each call to repo.Stage() will

  • Perform a diff between the working directory and the Index in order to determine what additions/removals should be promoted to the staging area
  • Perform additions/deletions in the in memory Index
  • Eventually persist the in memory Index to the disk

Each call to repo.Index.Add() (or Remove()) will

  • Perform an addition (or a deletion) in the in memory Index
  • Persist the in memory Index to the disk

As such, invoking repo.Index.Add() or repo.Index.Remove() will be more efficient than a call to repo.Stage().

We want to allow the user to switch to the command line git.git, between each call to LibGit2Sharp, and find the repository in a coherent state. This is the requirement that compels us to persist the in-memory Index at the very end of each Index related method.

However, would clients of the library require to perform many sequential calls to the lower level methods repo.Index.Add()|Remove(), the Index would be persisted as part of each call. Which may not be very efficient.

Considering this above, would a need for an IndexUpdater exist?

We may expose something like in the Index type:

public virtual void Update(params Action<IndexUpdater>[] actions)

which would allow the client to write such code:

repo.Index.Update(i => i.Add(path), i => i.Remove(otherPath))

Or even some more elaborate custom thingies such as

private void StageAllAdditionsRemovalsAndModifications(IRepository repo)
{
    // Compare the Workdir against the Index without attempting at detecting Copies/Renames
    var changes = repo.Diff.Compare<TreeChanges>(null, true,
        compareOptions: new CompareOptions { Similarity = SimilarityOptions.None });

    repo.Index.Update(i =>
    {
        // We first clean the Index from unwanted entries...
        foreach (TreeEntryChanges treeEntryChanges in changes
            .Where(tec => tec.Status == ChangeKind.Deleted))
        {
            i.Remove(treeEntryChanges.Path);
        }

        // ...then insert in the Index the additions/modifications.
        foreach (TreeEntryChanges treeEntryChanges in changes
            .Where(tec => tec.Status == ChangeKind.Added || tec.Status == ChangeKind.Modified))
        {
            i.Add(treeEntryChanges.Path);
        }
    });
}

And allow us to only persist the Index only once, when all the actions have been performed by the IndexUpdater.

Thoughts?

贡献指南

打开贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

调研方向

首先阅读 PR #907 以及现有的 Index.Add() 和 Index.Remove() 入口点。将提议的 Index.Update/IndexUpdater API 与“repository 在调用之间保持一致”的要求进行比较;要视为完成,需要一个经 maintainer 批准的设计和明确的实现范围,而本 RFC 尚未提供这些内容。

由索引模型根据 Issue 内容生成。

评估

技术栈
csharp, git
领域
backend-api-design
Issue 类型
功能
难度
5/5
预计耗时
一周以上
活跃度
停滞
描述清晰度
需要澄清
新手友好度
25/100

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。