RXL
|
|
« : 23-03-2010 18:45 » |
|
Заинтересовал меня вот такой аспект работы с репозиторием.
Имеется некий текстовый проект. Конкретно — сайт на PHP. Для контроля изменений импортируем его в SVN. Для продакшн делаем svn export. Вносим изменения на ходу в продакшн (например, правка конфига, шаблона, языкого файла, оперативный патч на код и т.п.). Теперь все эти изменения надо сохранить в репозитории: делаем svn checkout во временную директорию, копируем туда измененные файлы, делаем набор add/delete/move и финальный commit. Муторно и коряво. Особенно неудобно при апгрейде сайта, когда обновления массово вносятся сторонним скриптом (например, скрипт апргрейда от поставщика движка) — при этом изменяется большое количество файлов в самых разных директориях.
Как сделать иначе?
Скажем, поднять тестовый сайт, создать тестовую базу, залить данные, выполнить в директорию этого сайта checkout, выполнить обновление, тестирование сайта, выполнить commit. С файлами все ок: после делаем svn export для продакшн и все ОК. Но... база то не та обновилась. Делать апгрейд на тесте с продакшн базой? Тогда сайт лочить надо, чтобы не работал с базой на время апгрейда. Тогда нет смысла делать тестовый сайт, а делать checkout сразу на продакшн, а после commit удалять все и делать туда export. Все равно как-то некрасиво выходит. Например, проблемой может быть то, что в директориях сайта есть пользовательские файлы, которые в репозитории хранить бессмысленно: занимают много места, часто обновляются и к коду, который и призван контролировать репозиторий, отношения не имеет.
Третий вариант: в директории сайта постоянно хранится рабочая копия (результат checkout). Тогда проблемы вышеописанных методов исчезают. Но есть другие минусы: наличие директорий .svn в продакшн (в принципе, их легко скрыть настройками сервера) и двойной объем хранимых на сайте данных (это без учета пользовательских данных).
Может кто-нибудь знает лучший способ?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
baldr
|
|
« Ответ #1 : 23-03-2010 20:15 » |
|
RXL, правильных ответов, видимо, несколько.. в зависимости от сложности изменений.. Я если что-то небольшое меняю, то просто перекидываю на сайт измененные файлики по одному.. Если много поменял - svn export всей папки..
Добавлено в 2010-03-24, 00:16:51: еще вариант - делай еще одну папку с сайтом, туда кидай новую версию, меняй конфиг, а потом быстро переименовывай папку с рабочей и новой версией друг в друга..
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
Kivals
|
|
« Ответ #2 : 23-03-2010 20:48 » |
|
Чтобы не хранить двойной объем данных можешь использовать diff файлы: с помощью svn делаешь diff между ревизией на сайте и новой, потом коммандой patch применяешь изменения к сайту. Что касается лишних файлов в пользовательских каталогах - просто не вносишь их в репозиторий (не делаешь для этого каталога svn add) Что касается изменений базы - например Redmine написан так, что сам обновляет базу до нужной версии, т.е. скрипты обновления хранятся в скриптах приложения. ИМХО это правильное решение.
|
|
|
Записан
|
|
|
|
baldr
|
|
« Ответ #3 : 23-03-2010 21:03 » |
|
Kivals, diff не сделаешь, если сайт опубликован через svn export - придется делать checkout, что не очень правильно идеологически....
|
|
|
Записан
|
Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
|
|
|
RXL
|
|
« Ответ #4 : 23-03-2010 22:33 » |
|
Можно сделать diff! — Исключив директории '.svn': diff -x '\.svn' -r work-copy/www site/www >site.diff
Также можно исключить нежелательные директории: diff -x '\.svn' -x userdir -r work-copy/www site/www >site.diff
Но выражение фильтра не может работать с путем — только с именем файла или директории. Т.ч. если есть 'userdir' и 'data/userdir', то выпадут обе директории. Добавлено в 2010-03-24, 02:45:54:baldr, Kivals, по условию задачи изменения вносятся на сайт, а не в рабочую директорию! Исключение - вариант 3, но он неудобен (я описал — чем). Kivals, не мне говорить производителю ПО, как его обновлять... : Вот пришлось тут запасной форум апдейтить. Из-за множественных ручных изменений скрипт апгрейда не заработал и пришлось читать его и вносить изменения в базу самостоятельно. Я скажу, что такого ужаса я еще не наблюдал (рассказывать не буду — посмотрите сами на их сайте "large update" до 1.1.11). Главное — куда денешься... На работе есть ПО, которое при апгрейде инкрементально обновляет базу: база последовательно апдейтится на все версии между текущей и устанавливаемой версиями. Это, по моему, намного правильнее.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #5 : 24-03-2010 08:14 » |
|
не покатит? Про инкрементальное обновление я и писал (на примере Redmine) Не понял про производителя: если производитель не предусмотрел обновление базы при обновлении скриптов ПО - то к сожалению это ему большой жирный минус. Больше тут действительно ничего поделать нельзя, кроме выдирания из скрипта обновления именно части апдейта базы, а сами скрипты ПО - через diff (или как-то еще)
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #6 : 24-03-2010 11:27 » |
|
Kivals, не, не покатит. Исключительно basename понимает, а точнее — шаблон на basename. Про производителя — я привел пример апгрейда SMF, когда апгрейд базы выполняется PHP-скриптом, который рассчитан на апгрейд аж с древнейших версий и там жуткая система наложения изменений. Обновление же файлов приходится делать через diff и далее руками переносить — это из-за моих ручных изменений и негибкой архитектуры. Инкрементальные патчи, IMHO, удобнее всего. Обобщим технологию: 0. На сайте копия без поддержки Subversion (без файлов .svn). В ней были произведены правки и надо перенести их в репозиторий. (Например, директория www в текущей директории). 1. В отдельную директорию делаем svn checkout (Например, директория copy). 2. Создаем контекстный diff (почему-то с форматом normal потов возникают какие-то трудности при наложении патча): diff -x \\.svn -r -c copy www > patch.diff 3. Накладываем патч на рабочую копию: 4. Выполняем svn commit.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #7 : 24-03-2010 17:12 » |
|
Можно вести "родные" версии SMF в своем репозитории как главный проект, а изменения для нашего форума - как ветвь от главного. Тогда вроде бы легче должно проходить слияние. Кроме того это направление (удобство работы с ветвями) сейчас активно развивается в svn. Сам пока еще не разбирался...
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #8 : 24-03-2010 18:05 » |
|
Мне еще не приходилось сталкиваться со слиянием ветвей — пока только объединял конфликтующие правки (И как я умудрился, являясь единственным разработчиком? Вероятно откатывался на предыдущую ревизию и переделывал.)
Идея интересная — попробую реализовать. Жаль, только то, что обновления SMF выходят примерно раз в полгода-год — эксперимент растягивается.
Если бы они еще и апдейт базы делали инкрементально, было бы совсем хорошо.
Применить SVN к Шелеку я взялся когда чат прикручивали — чтобы легче было переносить изменения с тестового форума на основной. Вспомнить, что и зачем я в коде поправил года три-четыре назад — совсем нереально. Даже комментарии не помогают. Теперь проще.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #9 : 24-03-2010 19:01 » |
|
Так и не надо вспоминать - берешь версию разработчиков, до которой обновил сейчас, делаешь из нее ветвь, потом поверх накатываешь существующие файлы и commit-ишь - svn тебе сам покажет различия и запомнит ветку. Пример: есть архивы версий: 001 (основан на версии 0.1 разработчика) 002 (на версии 0.1) 003 (на версии 0.2)
Пишем в основную ветку svn версию 0.1 разработчика, создаем нашу ветвь, commit накатываем на нашу ветвь архив 001, commit накатываем на нашу ветвь архив 002, commit В основную ветвь commit версию 0.2 разработчика объединяем нашу ветвь с основной веткой (подробностей не знаю), возможно - commit накатываем архив 003, commit
Ну а с апдейтом базы надо думать... Есть верификаторы баз, которые создают SQL запросы для перевода ее из одного состояния в другое, но я видел только платные. Т.е.: создаем пустой проект версии 0.1 - разворачиваем базу 1, создаем пустой проект 0.2, разворачиваем базу 2. Сравниваем и получаем скрипт инкрементного апдейта базы от версии 0.1 к версии 0.2
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #10 : 24-03-2010 19:20 » |
|
С базами значительно сложнее: структура без живых данных не имеет смысла, а текущие данные в старую структуру не вольешь. Остается делать полные бекапы базы на момент изменения. Это я о конкретном примере поддержания Шелека — если просто поддержание истории изменения структуры, то да — можно и в SVN залить.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #11 : 24-03-2010 20:35 » |
|
Ну полный бакап базы никто не отменял при обновлении, а обновить ее - я так понимаю это добавить новые таблицы/колонки, что-то типа: ALTER TABLE ... ADD COLUMN ...
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #12 : 24-03-2010 21:10 » |
|
По мере экспериментов, параметры уточняются: diff -x \\.svn -ruaN copy www > patch.diff Ключ -N добавит в diff новые файлы, отсутствовавшие в старой версии, или будет обнулять старые файлы, если их нет в новой версии. patch -p0 -uET <patch.diff Ключ -E удалит пропатченные файлы, еслт в результате их правки он стали пустые. Ключ -T установит пропатченонго файла mtime от файла новой версии. В обеих командах сменил формат на unified, как более компактный, чем context. Удаление директорий в новой версии патчем никак не контролируется. Кстати, все равно нужно делать svn delete. Провел эксперимент с заливкой исходного дистрибутива в репозиторий, созданием ветки и наложением на нее патча. Пока успешно. Репозиторий сделал отдельный. Как выйдет новое обновление — опробую слияние. Чую, это будет еще тот геморрой. Кстати, при апгрейде базы нередко еще и данные обновляются.
|
|
« Последнее редактирование: 24-03-2010 21:12 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #13 : 25-03-2010 06:21 » |
|
Кстати, при апгрейде базы нередко еще и данные обновляются. Вот это наверное придется в ручном режиме выдирать из скрипта обновления поиском по INSERT & UPDATE Но по идее такого не много должно быть
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #14 : 25-03-2010 10:30 » |
|
Обновление на скриптах, вместо SQL-процедур, делают из-за совместимости с различными хостингами. К сожалению. Лучше бы хостинги ориентировались на потребности, чем наоборот.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #15 : 25-03-2010 11:06 » |
|
В идеале конечно хотелось бы иметь оба варианта, причем чтобы вариант "на скриптах" автоматически генерировался из варианта "SQL". Эту мысль нужно запомнить для своих проектов
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #16 : 25-03-2010 13:18 » |
|
Думаешь парсить SQL_процедуры?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #17 : 25-03-2010 15:31 » |
|
Тут 2 варианта: либо парсить процедуры, в принципе достаточно определить начало-конец одного блока и запихать все это в один вызов из скрипта - и так по каждому блоку либо описывать все это дело в xml, а потом из него формировать SQL для разных диалектов (при поддержке разных СУБД) и скрипты тоже из него
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #18 : 25-03-2010 18:44 » |
|
Если курсоры и переменные используются, то из скрипта не получится.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #19 : 25-03-2010 19:07 » |
|
тогда надо через create function ... drop function
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #20 : 26-03-2010 04:46 » |
|
Вот я тоже думаю, что это самый правильный и гуманный способ.
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
RXL
|
|
« Ответ #21 : 09-11-2010 20:29 » |
|
Был у меня сейчас чудесный глюк. Делал все, как сам же описал в посте №12. Патч создался правильный - я его внимательно просмотрел. А вот когда начал патчить рабочую копию, то вместо нее патч начал применяться в обратную сторону...
diff -x \\.svn -ruaN work_copy /path/src_dir > patch.diff patch -p0 -uET <patch.diff
Пропатчилось src_dir. Чудеса...
Когда переименовал src_dir, то патч лег правильно - на work_copy. Никто больше с таким не сталкивался?
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
Kivals
|
|
« Ответ #22 : 10-11-2010 08:44 » |
|
Могу и ошибиться, но мне кажется что выполнение patch -p0 -uET <patch.diff
зависит от текущего каталога...
|
|
|
Записан
|
|
|
|
RXL
|
|
« Ответ #23 : 10-11-2010 13:32 » |
|
Да, видимо оно так и есть. Сейчас столкнулся с этим повторно:
diff -ruaN old new > patch.diff patch -p0 -uET < patch.diff
Опять он попытался патчить "new". Не понимаю такого поведения.
Сделал так:
cd old diff -ruaN ./ ../new > ../patch.diff patch -p0 -uET < ../patch.diff
Отработало как надо.
Доку пробовал читать, но уж очень она путаная - то об одном формате, то о другом, а чаще о "мусоре".
|
|
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
RXL
|
|
« Ответ #24 : 20-11-2010 18:35 » |
|
Либо я тупой, либо это шаманство. $ ls temp trunk $ cd trunk $ diff -x \.svn -ruaN www/Themes ../temp/Themes >patch-Themes.diff $ patch -p0 -uET <patch-Themes.diff The next patch would create the file ../temp/Themes/default/images/bbc/expand.gif, which already exists! Assume -R? [n] <Нажал ctrl-c> $ cd www $ patch -p1 -uET <../patch-Themes.diff patching file Themes/default/images/bbc/expand.gif patching file Themes/default/Post.template.php patching file Themes/PooH/images/bbc/expand.gif patching file Themes/VU3/images/bbc/expand.gif
Почему?.........
|
|
« Последнее редактирование: 20-11-2010 18:37 от RXL »
|
Записан
|
... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
|
|
|
|