beldmit: (Программизм)
Dmitry Belyavskiy ([personal profile] beldmit) wrote2024-12-25 04:30 pm

Как нам обустроить патчи

Сгребу-ка я сюда все свои не очень оформленные мысли, а заодно и ссылки.

Вводная. У меня есть два основных пакета, с которыми я на работе ковыряюсь, OpenSSH и OpenSSL. И там и там 60+ патчей, которые при каждом ребейзе приносят адскую боль. OpenSSL я знаю хорошо и поэтому с этой болью я почти смирился, OpenSSH я знаю средне.

Случаи, когда код переписан содержательно, всегда требуют индивидуального подхода и деваться от этого некуда. Но хочется минимизировать технические вещи.

Очевидно, что чисто по времени при ребейзе дофига жрут сцепленные патчи. Мы поправили строку из контекста, и теперь у нас конфликт. Мы решили конфликт, нарушив тем самым контекст следующего патча. Возможно, эти два патча стоит склеить в один (или нет, если они решают разные проблемы). Но для этого их надо идентифицировать как "сцепленные".

Ещё очевидно, что патчи к одной подсистеме лучше прикладывать подряд, потому что контекст (в голове). И опять же склеить там, где возможно.

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

Номера затронутых строк и строк контекста так просто из patch/diff не получить. Во всяком случае, я не нашёл. Ну теоретически эту часть я могу хоть на Perl написать, не rocket science. Найти сцепленные патчи так можно, и дальше уже решать, что с этим делать.

Следующий интересный вопрос - а что ещё с этим можно сделать, чтобы улучшить поддерживаемость набора патчей in the long run.

На уровне разработки я нашёл совершенно чудный инструмент git absorb, который разбирает свежие изменения на fixup-ы и новые содержательные. Не знаю, как он потянет 60+ коммитов, конечно.

Вот тут пишут про замену diff для GitHub, но в основном для web-интерфейса.

Difftastic - продвинутый diff, не по строкам, а по логическим блокам

Mergiraf - продвинутый merge.

В дискуссию приглашается, например, [personal profile] spamsink
yurikhan: (Default)

[personal profile] yurikhan 2024-12-25 04:35 pm (UTC)(link)

На тему git absorb ещё есть git autofixup. Кажется, с немного другим принципом действия, но той же решаемой задачей.

vitus_wagner: My photo 2005 (Default)

[personal profile] vitus_wagner 2024-12-25 05:05 pm (UTC)(link)

Ну как не получить номера строк?

Берем типичный патч, context unified diff. И ччто мы там видим?

--- a/tests/playTests.sh
+++ b/tests/playTests.sh
@@ -1857,8 +1857,13 @@

Вот то что после @@ это номер первой строки блока и через запятую количество затрнутых строк.

vitus_wagner: My photo 2005 (Default)

[personal profile] vitus_wagner 2024-12-25 08:01 pm (UTC)(link)

Они имеют самое прямое отношение к реальности той версии, куда они накладываются без fuzz.

В debian процесс приведения патчей к текущему состоянию кода автоматизирован посредством утилиты quilt.

dimas: (Default)

[personal profile] dimas 2024-12-25 05:15 pm (UTC)(link)
А с какой стороны у тебя больше патчей - твои локальные или что приходит из мейнстрима? Может надо просто в другую сторону мержить?

Потом, я бы посмотрел на твой набор патчей, если таки их меньше, чем мейнстрим меняется ... Возможно, их можно поделить на части, которые будут проще автоматом применяться к мейнстриму.

dft и mf я себе в конфигурацию прикрутил, но пока особо не использовал.
vitus_wagner: My photo 2005 (Default)

[personal profile] vitus_wagner 2024-12-25 05:20 pm (UTC)(link)

В другую сторону не получится, потому что патч не просто меняет несколько строчек кода, но еще и документирует это изменение.

dimas: (Default)

[personal profile] dimas 2024-12-25 05:21 pm (UTC)(link)
И почему из-за этого не получится?
vitus_wagner: My photo 2005 (Default)

[personal profile] vitus_wagner 2024-12-25 05:28 pm (UTC)(link)

Потому что патчи, применямые мейнтейнером пакета в дистрибутиве лежать в src.rpm отдельно от апстримовского тарболла. А тарболл должен быть именно апстримовским.

dimas: (Default)

[personal profile] dimas 2024-12-25 05:30 pm (UTC)(link)
М-м-м ... Разве мы говорим не про разные части задачи?

Нам сначала надо взять мэйнстримное текущее состояние, и наложить на него все имеющиеся "наши" патчи. И только после того, как у нас все нормально наложилось, проектировалось и т.д, уже идет шаг изготовления текущего набора патчей, которые будут упакованы в этот rpm?
dimas: (Default)

[personal profile] dimas 2024-12-25 05:38 pm (UTC)(link)
Ну, как ты понимаешь, я имел в виду втянутое из апстрима как вторую сторону. Ты же их наверняка хранишь в отдельном бранче?

[personal profile] alexott 2024-12-25 06:41 pm (UTC)(link)
juan_gandhi: (Default)

[personal profile] juan_gandhi 2024-12-25 09:37 pm (UTC)(link)
Да я вообще пока что не вижу такой науки, которая бы решала эту задачу.
livelight: (Default)

[personal profile] livelight 2024-12-26 10:29 am (UTC)(link)
Но зачем ребейз?!
livelight: (Default)

[personal profile] livelight 2024-12-26 10:48 am (UTC)(link)
Не очень понимаю, что у вас за процесс. Если мейнтейнер апстрима начнёт ребейзить ключевые ветки, то в них одни коммиты превратятся в другие, и в тыкву превратится примерно всё у примерно всех в даунстримах. Почему ребейзы, а не нормальные мержи?
livelight: (Default)

[personal profile] livelight 2024-12-26 11:07 am (UTC)(link)
Но зачем ребейз?
Каждый патч знает, от какого коммита он отрос, и при мерже номера строк автоматически сдвигаются, куда надо. Блейм после мержа обычно тоже вразумительный, кроме мест с конфликтами. Даунстрим, патч от которого принят, знает свой коммит и не удивляется, увидев его клон после ребейза. В общем, сплошные плюсы.
Единственный минус стандартного гитового мержа - что после него бывает сложно понять, что было в той же ветке до мержа, а что приехало с мержом, так что бисекция может показывать лажу, ну так эту проблему ребейз тоже не решает.
Edited 2024-12-26 11:08 (UTC)
livelight: (Default)

[personal profile] livelight 2024-12-26 11:38 am (UTC)(link)
Я правильно понимаю, что "изменения в апстриме" - это как раз и есть ребейзы? Мержи - это append-only изменения, после них старые патчи обычно прикладываются (если только не возникли текстуально конфликтующие изменения одних и тех же строк).
yurikhan: (Default)

[personal profile] yurikhan 2024-12-26 01:04 pm (UTC)(link)

Процесс пакетирования программы или библиотеки для Debian («дебианизация») состоит в том, что Мейнтейнер берёт релизный слепок исходников Апстрима и обеспечивает, чтобы этот слепок собирался в контексте целевой версии системы и удовлетворял представлениям Debian’а о прекрасном. (Использует системные версии библиотек, а не таскает свои; не содержит несвободных или нарушающих прайваси компонентов; не имеет функциональности самообновления в обход apt’а и пр.) Иногда для этого приходится менять исходники, таким образом получаются патчи.

Веселье здесь в том, что процесс не требует от Апстрима использования Git’а. И даже вообще какой-нибудь системы контроля версий. От Апстрима требуется предоставлять тарболы тех версий, которые он считает стабильными, остальное забота Мейнтейнера.

Более того, когда конечный пользователь говорит в шелле apt-get source {somepackage}, то ему приезжает исходный тарбол Апстрима + патчи от Мейнтейнера, это часть контракта. Так что Мейнтейнеру нельзя локально смёржить свои патчи и время от времени подмёрживать Апстрим и собирать бинарные пакеты. Нужно уметь выдать наружу версию серии патчей, соответствующую каждому релизу.

Вот процесс получения серии патчей для нового релиза, когда есть тарболы старого и нового релизов, и называется обобщённо ребейзом, и это не обязан быть буквально git rebase, иногда это последовательность quilt push — чиним реджекты — quilt refresh — следующий quilt push — пока не наложатся все патчи.

livelight: (Default)

[personal profile] livelight 2024-12-27 10:53 am (UTC)(link)
То есть, патчи для готового релиза (включая, возможно, бинарники), а не для сорцов? Тогда это вообще пипец задачка - множественные патчи для такого держать.
yurikhan: (Default)

[personal profile] yurikhan 2024-12-27 11:17 am (UTC)(link)

Не, патчи для сорцов. Но (1) сорцы не обязаны лежать в гиту, (2) конечный пользователь должен мочь собрать бинарники из сорцов с патчами самостоятельно, и (3) конечный пользователь должен мочь читать патчи по отдельности.

С оценкой нелёгкой доли мейнтейнеров согласен, хоть бы бинарники патчить и не приходилось.