Форум программистов «Весельчак У»
  *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

  • Рекомендуем проверить настройки временной зоны в вашем профиле (страница "Внешний вид форума", пункт "Часовой пояс:").
  • У нас больше нет рассылок. Если вам приходят письма от наших бывших рассылок mail.ru и subscribe.ru, то знайте, что это не мы рассылаем.
   Начало  
Наши сайты
Помощь Поиск Календарь Почта Войти Регистрация  
 
Страниц: [1]   Вниз
  Печать  
Автор Тема: Принципы работы с репозиторием (на примере Subversion).  (Прочитано 32269 раз)
0 Пользователей и 5 Гостей смотрят эту тему.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« : 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
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #1 : 23-03-2010 20:15 » 

RXL, правильных ответов, видимо, несколько.. в зависимости от сложности изменений..
Я если что-то небольшое меняю, то просто перекидываю на сайт измененные файлики по одному.. Если много поменял - svn export всей папки..

Добавлено в 2010-03-24, 00:16:51:
еще вариант - делай еще одну папку с сайтом, туда кидай новую версию, меняй конфиг, а потом быстро переименовывай папку с рабочей и новой версией друг в друга..
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #2 : 23-03-2010 20:48 » 

Чтобы не хранить двойной объем данных можешь использовать diff файлы: с помощью svn делаешь diff между ревизией на сайте и новой, потом коммандой patch применяешь изменения к сайту.
Что касается лишних файлов в пользовательских каталогах - просто не вносишь их в репозиторий (не делаешь для этого каталога svn add)
Что касается изменений базы - например Redmine написан так, что сам обновляет базу до нужной версии, т.е. скрипты обновления хранятся в скриптах приложения. ИМХО это правильное решение.
Записан
baldr
Команда клуба

cy
Offline Offline
Пол: Мужской
Дорогие россияне


WWW
« Ответ #3 : 23-03-2010 21:03 » 

Kivals, diff не сделаешь, если сайт опубликован через svn export - придется делать checkout, что не очень правильно идеологически....
Записан

Приличный компьютер всегда будет стоить дороже 1000 долларов, потому что 500 долларов - это не вполне прилично
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #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
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #5 : 24-03-2010 08:14 » 

Код:
-x '/userdir'
не покатит?

Про инкрементальное обновление я и писал (на примере Redmine)
Не понял про производителя: если производитель не предусмотрел обновление базы при обновлении скриптов ПО - то к сожалению это ему большой жирный минус. Больше тут действительно ничего поделать нельзя, кроме выдирания из скрипта обновления именно части апдейта базы, а сами скрипты ПО - через diff (или как-то еще)
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #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. Накладываем патч на рабочую копию:

Код:
patch -p0 -c <patch.diff

4. Выполняем svn commit.

Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #7 : 24-03-2010 17:12 » 

Можно вести "родные" версии SMF в своем репозитории как главный проект, а изменения для нашего форума - как ветвь от главного. Тогда вроде бы легче должно проходить слияние. Кроме того это направление (удобство работы с ветвями) сейчас активно развивается в svn. Сам пока еще не разбирался...
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #8 : 24-03-2010 18:05 » 

Мне еще не приходилось сталкиваться со слиянием ветвей — пока только объединял конфликтующие правки (И как я умудрился, являясь единственным разработчиком? Вероятно откатывался на предыдущую ревизию и переделывал.)

Идея интересная — попробую реализовать. Жаль, только то, что обновления SMF выходят примерно раз в полгода-год — эксперимент растягивается.

Если бы они еще и апдейт базы делали инкрементально, было бы совсем хорошо.

Применить SVN к Шелеку я взялся когда чат прикручивали — чтобы легче было переносить изменения с тестового форума на основной. Вспомнить, что и зачем я в коде поправил года три-четыре назад — совсем нереально. Даже комментарии не помогают. Теперь проще.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #9 : 24-03-2010 19:01 » new

Так и не надо вспоминать - берешь версию разработчиков, до которой обновил сейчас, делаешь из нее ветвь, потом поверх накатываешь существующие файлы и 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
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #10 : 24-03-2010 19:20 » 

С базами значительно сложнее: структура без живых данных не имеет смысла, а текущие данные в старую структуру не вольешь. Остается делать полные бекапы базы на момент изменения. Это я о конкретном примере поддержания Шелека — если просто поддержание истории изменения структуры, то да — можно и в SVN залить.


Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #11 : 24-03-2010 20:35 » 

Ну полный бакап базы никто не отменял при обновлении, а обновить ее - я так понимаю это добавить новые таблицы/колонки, что-то типа:
ALTER TABLE ... ADD COLUMN ...
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #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
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #13 : 25-03-2010 06:21 » 

Кстати, при апгрейде базы нередко еще и данные обновляются.
Вот это наверное придется в ручном режиме выдирать из скрипта обновления поиском по INSERT & UPDATE Жаль Но по идее такого не много должно быть
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #14 : 25-03-2010 10:30 » 

Обновление на скриптах, вместо SQL-процедур, делают из-за совместимости с различными хостингами. К сожалению. Лучше бы хостинги ориентировались на потребности, чем наоборот.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #15 : 25-03-2010 11:06 » 

В идеале конечно хотелось бы иметь оба варианта, причем чтобы вариант "на скриптах" автоматически генерировался из варианта "SQL". Эту мысль нужно запомнить для своих проектов Улыбаюсь
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #16 : 25-03-2010 13:18 » 

Думаешь парсить SQL_процедуры? Улыбаюсь
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #17 : 25-03-2010 15:31 » 

Тут 2 варианта:
либо парсить процедуры, в принципе достаточно определить начало-конец одного блока и запихать все это в один вызов из скрипта Улыбаюсь - и так по каждому блоку
либо описывать все это дело в xml, а потом из него формировать SQL для разных диалектов (при поддержке разных СУБД) и скрипты тоже из него
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #18 : 25-03-2010 18:44 » 

Если курсоры и переменные используются, то из скрипта не получится.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Kivals
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #19 : 25-03-2010 19:07 » 

тогда надо через create function ... drop function
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #20 : 26-03-2010 04:46 » 

Вот я тоже думаю, что это самый правильный и гуманный способ.
Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #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
Команда клуба

ca
Offline Offline
Пол: Мужской

WWW
« Ответ #22 : 10-11-2010 08:44 » 

Могу и ошибиться, но мне кажется что выполнение
patch -p0 -uET <patch.diff

зависит от текущего каталога...
Записан
RXL
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #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
Технический
Администратор

Offline Offline
Пол: Мужской

WWW
« Ответ #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 » Записан

... мы преодолеваем эту трудность без синтеза распределенных прототипов. (с) Жуков М.С.
Страниц: [1]   Вверх
  Печать  
 

Powered by SMF 1.1.21 | SMF © 2015, Simple Machines