libgit2 / libgit2/libgit2sharp
[RFC] Batched low level index operations
まだ誰も着手していません。
- 主要言語
- 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?
コントリビューションガイド
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
調査の方向性
まず PR #907 と、既存の Index.Add() および Index.Remove() のエントリーポイントを確認してください。提案されている Index.Update/IndexUpdater API を、呼び出し間で repository の整合性を維持するという要件と比較してください。完了とするには、maintainer が承認した設計と、定義済みの実装スコープが必要ですが、この RFC にはまだそれらがありません。
索引モデルが issue の本文から書いたものです。
評価
- 技術スタック
- csharp, git
- 領域
- backend-api-design
- issue の種類
- 機能追加
- 難易度
- 5/5
- 見積もり時間
- 1週間以上
- 活発さ
- 停滞
- 明瞭さ
- 説明が足りない
- 初心者へのやさしさ
- 25/100