On Thu, Nov 08, 2007 at 08:42:25PM +0300, Dmitry V. Levin wrote: > Сборка транзакции (A) происходит следующим образом: > - создаётся репозиторий - снапшот текущего опубликованного Сизифа (Ra); > использование ссылок делает эту операцию дешевой; > - на этом снапшоте выполняется сборка --with-stuff исходных пакетов > транзакции; если хотя бы один не собрался, то транзакция отменяется > (в первой реализации сборочной системы не вижу смысла оптимизировать > эту часть); Здесь есть тонкость: сборка --with-stuff второго и последующего пакетов транзакции идёт со СТАРЫМИ contents_index_bin и contents_index_all. То есть практика сборки --with-stuff потенциально может давать неправильныме зависимости -- сразу же после фиксации транзакции второый и последующие пакеты при тестовой пересборке могут получить отличающиеся зависимости. Так что здесь есть несколько подходов: 0) забить; 0a) пока забить; 1) делать в хешере локальный contents_index_bin/all; 2) формировать временный сизиф после каждого пакета транзакции и вести сборку уже на нём. Это всё равно не до конца решает вопрос, если зависимостями между пакетами в транзакции топологически не упорядочены (то есть напр. при сборке первого пакета в транзакции используется старая сборка одного из последующих пакетов). > - на основе Ra и свежесобранных пакетов формируется новый Сизиф (Ra'); > - сравниваются анметы Ra и Ra'; > в случае появления новых анметов транзакция откладывается; > - вычисляется множество (Sa') исходных пакетов в Ra', для сборки которых > требуются свежесобранные пакеты транзакции A (точнее говоря, в сборочной > среде которых присутствует хотя бы один из свежесобранных пакетов); > - на Ra' выполняется тестовая сборка всех пакетов из Sa'; > - если хотя бы один пакет перестал собираться (по сравнению со статистикой > сборки на Ra), то транзакция откладывается; > - (*) предпринимается попытка применить успешно собранную транзакцию к Сизифу; > если опубликованный на этот момент Сизиф совпадает с тем Сизифом, на > основе которого был создан снапшот Ra, то происходит fast forward: > Ra' становится Сизифом, которому присваивается очередной номер; До сих пор всё правильно. Дальше самое трудное. > в противном случае предпринимается попытка выполнить rebase: > - создаётся репозиторий - снапшот текущего опубликованного Сизифа (Rb); > - вычисляется множество (Nab) пакетов, которое появилось/обновилось в Rb по > сравнению с Ra; здесь предполагается, что один и тот же исходный пакет > не может попасть в более чем одну незавершённую транзакцию; > - если в транзакции есть пакеты более старой сборки, чем одноимённые пакеты > в Nab, то транзакция отменяется (в первой реализации сборочной системы > не вижу смысла оптимизировать эту часть); Это нужно описать более точно ("алгебраически"). Имеется такая "структура коммитов" в метарепозитарии: * Rb (HEAD) | * ... branch Ra' * | `* Ra Я на самом деле всегда об этом думал в терминах специальной "стратегии мёржа" метарепозитария, и эта идея казалась мне полдотвороной. Теперь предлагается вместо мёржа делать ребейс. Вообще-то ребейс хуже мёржа, но в данном случае речь идёт примерно об одной и той же алгебраической операции. Мы хотим "насадить" изменение Ra->Ra' "сверху" на Rb. То есть имеются изменения Nab=Ra->Rb' и Naa'=Ra->Ra'. Можно ли их совместить "без конфликтов"? (Важное замечание. По сути речь идёт КРИТЕРИИ ВОЗМОЖНОСТИ мёржа/ребейса. Этот критерий говорит о том, что эта операция ЛИБО ВОЗМОЖНА, ЛИБО НЕВОЗМОЖНА. Это замечание можно переформулировать так: нельзя ребейсить что угодно на что угодно.) Изменение Ra->Ra' в общем виде состоит в следующем следующем: удалился src.rpm пакет liba1 NSVR1 вследствие чего удалился (arch|noarch).rpm пакет liba1-x NSVR1 удалился (arch|noarch).rpm пакет liba1-у NSVR1 ... добавился src.rpm пакет liba2 NSVR2 вследствие чего добавился (arch|noarch).rpm пакет liba2-x NSVR2 добавился (arch|noarch).rpm пакет liba2-x NSVR2 ... ... Замещение специальным образом рассматривать не надо -- оно сводится к удалению+добавлению. Простейший критерий мёржа/ребейса состоит в том, что должна сохраниться возможность 1) удаления старых пакетов, с точностью до всех версий; и 2) добавления всех новых пакетов, без точности по версии. А именно, попытка ребейса на Rb ПОСЛЕДОВАТЕЛЬНО проверяет возможность применения к Rb операций: rm src.rpm liba1 NSVR1 rm (arch|noarch).rpm liba1-x NSVR1 rm (arch|noarch).rpm liba1-y NSVR1 (если попытка удаления прошла хорошо, то считается, что всё реально удалилось) add src.rpm liba2 (если liba2.src.rpm какой-либо версии уже есть, то облом) add (arch|noarch).rpm liba2-x (если либо liba2-x.arch.rpm либо liba2-y.noarch.rpm уже есть, то облом) add (arch|noarch).rpm liba2-y Другими словами, это как бы "сильная" проверка на возможность "перекладывания" собранных пакетов. Она защищает от ситуации типа перерспила пакетов или перетасовки собранных пакетов между исходными. Но можно смотреть немного по-другому. Здесь нужен ещё один слой защиты от "частичного удаления" src.rpm пакетов. То есть должна быть алгебраическая операция "удалить src.rpm" пакет. src.rpm пакет может быть удалён только полностью, то есть в виде всех своих подпакетов. А новый src.rpm может быть добавлен тоже только полностью, в виде всех своих подпакетов. Тогда критерий сводится к тому, что нужно иметь возможность 1) полностью удалить тот же самый src.rpm пакет; 2) после удаления -- полностью добавить новый src.rpm, то есть его быть не должно (любой версии), ни каких-либо конфликтов по подпакетам (любых версий). > - на Rb заново собираются --with-stuff те пакеты из A, в сборочной среде > которых присутствуют пакеты из Nab; > - на основе Rb и собранных пакетов A формируется новый Сизиф (Rb'); > - сравниваются анметы Rb и Rb'; > в случае появления новых анметов транзакция откладывается; > - вычисляется множество (Sb') исходных пакетов в Rb', для сборки > которых требуется хотя бы один из свежесобранных пакетов; > - на Rb' выполняется тестовая сборка всех пакетов из Sb'; > если хотя бы один пакет перестал собираться (по сравнению со статистикой > сборки на Rb), то транзакция откладывается; > - предпринимается попытка применить успешно собранную транзакцию к Сизифу > по вышеописанному алгоритму, см. (*). Это рекурсивно что ли получается? Мне надо ещё подумать. Точнее, порисовать. > Из этого описания можно сделать выводы о том, что нужно для обработки > транзакции: > - бинарный репозиторий Сизиф для сборки пакетов; > - быстрое формирование нового бинарного репозитория Сизифа на основе > предыдущего и новых пакетов (есть ли у нас необходимые средства?); Насколько быстрое? Думаю что достаточно быстрое имеется. > - корректное вычисление анметов (действующий алгоритм apt-cache unmet, > по всей видимости, игнорирует конфликты); По крайней мере, если новый репозитарий правильно сформирован, то 'apt-cache unmet' помогает обнаруживать бездумную/unintented смену сонейма. > - быстрое вычисление подмножества исходных пакетов Сизифа, для сборки > которых требуется пакеты из указанного подмножества бинарных пакетов > Сизифа (у нас сейчас нет такого алгоритма); 30 минут на машине класса mash (см. мой query-rebuild.git). Но это может быть намного быстрее на каком-нибудь Core2Duo, и, следовательно, более приемлемо. > - статистика сборки исходных пакетов Сизифа должна быть частью Сизифа. Да. Частью метарепозитария. То есть нужно знать когда и в каком виде пакет последний раз собрался и кое-что ещё. > Формулировка "транзакция откладывается" означает, что дальнейшая обработка > транзакции невозможна без вмешательства извне. На практике это может > означать отмену транзакции, дополнение транзакции новыми исходными > пакетами (фактически формирование новой транзакции на основе отложенной), > или действия уполномоченных лиц по преодолению причин, из-за которых > транзакция была отложена. Чем мёрж хуже ребейса. При мёрже в метарепозитарии явно остаётся информация, что нечто сломалось и потом починилось. Это ИНТЕРЕСНО. При ребейсе эта информация исчезает, и кажется, что как-будто всё само шло хорошо и гладко.