Subversion обновляет внешние данные до даты - PullRequest
39 голосов
/ 26 марта 2009

Я работаю над крупным установленным проектом под контролем SVN. Многие части кодовой базы проверяются как внешние, но активно работают над другими людьми.
Я хотел обновить всю свою рабочую копию, внешние компоненты и все, чтобы она отражала заголовки различных репозиториев в определенный момент времени. Моя первая попытка была:

svn up -r'{20090324}'

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

Я использую систему Linux.

Ответы [ 12 ]

38 голосов
/ 31 августа 2010

Это неэффективно, так как вызывает svn update чаще, чем (обычно) требуется. В противном случае, это короткий сладкий:

Unix:

find . -name .svn -execdir svn update -r {2010-08-30} \;

Windows

forfiles /m .svn /s /c "cmd /c svn up -r {2010-08-30}"
8 голосов
/ 26 марта 2009

При использовании svn: externals обычно плохая идея использовать внешний без номера ревизии. Это означает, что становится трудно соотносить версию внешнего с версией содержащего проекта; Я знаю этот трудный путь, от попытки отследить некоторую историю в проекте, который содержал внешние элементы, и я должен был бы предположить, какая ревизия соответствовала ревизии в содержащем проекте (иногда это было раньше, потому что кто-то обновил внешний проект затем обновлял содержащий проект, иногда это было позже, потому что кто-то отредактировал файлы непосредственно во внешней проверке, а затем зафиксировал его).

Вместо этого, как подсказывает подсказка пара абзацев в разделе externals в книге о подрывной деятельности , вы всегда должны фиксировать внешние элементы с номером ревизии. Таким образом, всякий раз, когда вы извлекаете конкретную ревизию содержащего проекта, будет также извлечена соответствующая ревизия внешнего. Это означает немного больше работы, так как вам нужно каждый раз обновлять номер редакции в свойстве svn: externals (мы написали скрипт для этого автоматически), но в долгосрочной перспективе это гораздо лучшее решение.

edit : Вот скелет скрипта, который мы использовали (задача rake) для удобного обновления внешнего и поддержания всего синхронизированного.

desc 'Update external for this project (rake update_external r=17789)'
task :update_external do |t|
  rev = ENV['r']
  rev =~ /^\d+$/ or raise "Invalid SVN revision number: r=<#{rev}>"

  # Update the project.
  sh "svn update"

  URL = 'svn+ssh://example.com/external/trunk'
  sh "svn propset svn:externals 'external -r#{rev} #{URL}' containing/directory"

  # Update again -- to put the externals back to the right revision.
  sh "svn update"
end
3 голосов
/ 21 июня 2009

Это - лучшее решение проблемы, которую я нашел на сегодняшний день (это сложная проблема - разработчики Subversions должны исправить это в ядре) Этот пример касается, в частности, mplayer, но вы должны легко увидеть логику.

; fetch the rev I want without including the externals
svn checkout -r "$REV" --ignore-externals \
    svn://svn.mplayerhq.hu/mplayer/trunk

; grab the date of that rev from the svn info output
DATE=`svn info trunk|sed -n '/^Last Changed Date/s/.*: \(.*\) (.*/\1/p'`

; fetch the externals using that date
svn checkout -r "{$DATE}" \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libavutil \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libavformat \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libavcodec \
        svn://svn.mplayerhq.hu/ffmpeg/trunk/libpostproc
2 голосов
/ 05 марта 2014

Основано на ответе Дейва Коэна, но немного быстрее:

find . -name '.svn' -execdir svn up --ignore-externals -r '{2014-02-05}' \;
2 голосов
/ 26 марта 2009

У меня до сих пор нет идеального решения, но это близко:

svn propget svn:externals | sed -e 's/ .*$//g' | xargs svn up -r'{20090324}'

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

Я уверен, что есть лучшее регулярное выражение, которое решит проблему в общем, хотя.

Редактировать: На самом деле, чем больше я об этом думаю, тем больше проблем я вижу. Самым большим из них является то, что он использует svn: externals из текущей версии, а не svn: externals версии на указанную дату. Это даже сложнее, чем я думал.

1 голос
/ 31 октября 2012

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

Интуитивно я мог подумать, что проверка чего-либо из определенной даты будет рекурсивно «привязывать» внешний поиск к этой дате, даже если внешние указывают на некоторую ревизию HEAD. Но, ну, это не так.

1 голос
/ 31 января 2010

хорошая утилита, которая будет заморозить внешние данные пути. мы используем эту утилиту, чтобы заморозить внешние объекты после создания тега из ствола:

http://svnxf.codeplex.com/

1 голос
/ 26 марта 2009

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

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

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

Лично я придерживался мнения, что внешние элементы должны рассматриваться и выпускаться как независимые проекты, поэтому все внешние элементы указывают на теги. Во время интенсивной параллельной разработки можно «переключить» внешнюю на внешнюю линию или иметь нестабильную ветвь разработки, временно указывающую на внешнюю линию, но основная линия проекта всегда указывает на стабильное внешнее соединение, и это сознательное решение для обновления. Это представление может быть излишним для вашей ситуации, но стоит посмотреть другие возможности.

0 голосов
/ 22 мая 2013

Пусть SVN сделает для вас рекурсию.

Tempfile и tee только здесь, чтобы вы могли видеть полный вывод:

SVN_UP_OUTPUT=$(mktemp SVN_UP_OUTPUT.XXXXX)
svn up -r$REVISION | tee $SVN_UP_OUTPUT
cat $SVN_UP_OUTPUT | egrep '^Fetching external' | egrep -o "'.*'" | sed -e "s/'//g" | while read DIR;do
    echo $$ svn up -r$REVISION "$DIR"
    svn up -r$REVISION "$DIR"
done
rm $SVN_UP_OUTPUT

Если вы не заботитесь о выводе, его можно сократить до следующего:

svn up -r$REVISION | egrep '^Fetching external' | egrep -o "'.*'" | sed -e "s/'//g" | while read DIR;do
    svn up -r$REVISION "$DIR"
done

И, конечно же, в вашем случае:

REVISION='{20090324}'
0 голосов
/ 24 августа 2012

Поскольку у меня недавно была похожая проблема, я написал небольшой скрипт для извлечения репозитория с определенной ревизией, а также проверки внешних элементов на дату этой ревизии: https://gist.github.com/3413952

Полезно, если вам нужно найти источник ошибки и хотите иметь нечто похожее на функцию git bisect.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...