Можно ли получить происхождение строк в конфликте слияния diff3 или составном diff в libgit2?

Я знаю, как сгенерировать файл, содержащий diff3: просто скопируйте после теста diff3.

Предположим, что diff3 будет содержать:

context1
<<<<<<< master
ours
||||||| base
base
=======
theirs
>>>>>>> topic
context2

Что я хочу, чтобы получить следующую карту:

line        origin
-------------------
context1 -> CONTEXT
ours     -> OURS
base     -> BASE
theirs   -> THEIRS
context2 -> CONTEXT

возможно, в цикле обратного вызова, как это делается для строк сравнения на git_diff_print, который передает git_diff_line обратному вызову, который содержит атрибут origin со значениями типа GIT_DIFF_LINE_CONTEXT

Конечно, я мог бы разобрать файл и поискать маркеры конфликта <<<, но это привело бы к неоднозначности, если бы сам файл содержал маркеры, поэтому я не хочу этого делать.

В качестве альтернативы, если бы я мог получить составной diff (формат diff по умолчанию во время разрешения конфликта слияния), как:

  context1
++<<<<<<< master
 +ours
++||||||| base
++base
++=======
+ theirs
++>>>>>>> topic
  context2

это также было бы возможным решением, так как в этом формате не может быть двусмысленности из-за символов + и пробела. Это, однако, было бы менее хорошо, так как мне все равно пришлось бы вручную анализировать вещи, для которых libgit2 уже имеет проанализированную информацию, которую он использовал для создания файла в первую очередь.

Я хочу сделать это, потому что внедряю инструмент разрешения слияний для GitLab: https://github.com/gitlabhq/gitlabhq/pull/7345

Изменить

Поскольку это кажется невозможным, я сделал предложение с интерфейсом по адресу: https://github.com/libgit2/libgit2/issues/2568


person Ciro Santilli 新疆再教育营六四事件ۍ    schedule 15.09.2014    source источник


Ответы (1)


Нет, libgit2 не предоставляет произвольного трехэтапного инструмента сравнения/слияния, который вы можете использовать: хотя он использует инструмент сравнения/слияния внутри себя для объединения файлов, он не предоставляет вызывающим сторонам способ получить кусок Информация об объединенных данных.

Вместо этого вы должны использовать любой инструмент сравнения/слияния по вашему выбору. (git и libgit2 используют библиотеку xdiff, хотя вы можете использовать любую библиотеку по своему усмотрению.)

Получить конфликтные данные из индекса для некоторого файла с именем filename в репозитории repo очень просто, а затем вы можете передать их своему инструменту:

git_index *index;
git_odb *odb;
git_index_entry *ancestor, *ours, *theirs;
git_odb_object *ancestor_file = NULL, *ours_file = NULL, *theirs_file = NULL;
const void *ancestor_data = NULL, *ours_data = NULL, *theirs_data = NULL;
size_t ancestor_size = 0, ours_size = 0, theirs_size = 0;

git_repository_index(&index, repo);
git_repository_odb(&odb, repo);

ancestor = git_index_get_bypath(index, filename, 1);
ours = git_index_get_bypath(index, filename, 2);
theirs = git_index_get_bypath(index, filename, 3);

if (ancestor) {
  git_odb_read(&ancestor_file, odb, &ancestor->id);

  ancestor_data = git_odb_object_data(ancestor_file);
  ancestor_size = git_odb_object_size(ancestor_file);
}

if (ours) {
  git_odb_read(&ours_file, odb, &ours->id);

  ours_data = git_odb_object_data(ours_file);
  ours_size = git_odb_object_size(ours_file);
}

if (theirs) {
  git_odb_read(&theirs_file, odb, &theirs->id);

  theirs_data = git_odb_object_data(theirs_file);
  theirs_size = git_odb_object_size(theirs_file);
}

/*
 * At this point, you can feed `ancestor_data`, `ours_data` and
 * `theirs_data` in to your diff/merge tool.  They are byte arrays
 * containing the contents of the file and are `ancestor_size`,
 * `ours_size` and `theirs_size` bytes long, respectively.
 *
 * If one any was `NULL`, then the conflict does not include
 * that side of the file, in the case of an add/add conflict or
 * if one side was deleted.
 */

git_odb_object_free(ancestor_file);
git_odb_object_free(ours_file);
git_odb_object_free(theirs_file);

(Обратите внимание, что этот код не тестировался, и обратите внимание на отсутствие проверки ошибок.)

person Edward Thomson    schedule 15.09.2014
comment
Спасибо, Эдвард. Как вы думаете, это то, для чего libgit2 рассмотрит запрос на вытягивание, или это выходит за рамки? Я чувствую, что это очень близко к функциональности, предоставляемой diff3/diff_print, и реализовано git. В противном случае я думаю, что просто проанализирую вывод составного diff git на Grit. - person Ciro Santilli 新疆再教育营六四事件ۍ 15.09.2014
comment
@CiroSantilli Я не знаю - я бы спросил других участников libgit2 по адресу github.com/libgit2/libgit2/ вопросы - person Edward Thomson; 15.09.2014
comment
Я сделал предложение с прототипом интерфейса по адресу: github.com/libgit2/libgit2/issues/2568. - person Ciro Santilli 新疆再教育营六四事件ۍ 16.09.2014