Синхронизация всех проектов Visual Studio с библиотекой - PullRequest
12 голосов
/ 16 января 2010

Сценарий

У меня есть библиотека, которая содержит проекты A, B и C.

У меня есть два решения. Решение 1 включает в себя копию проекта A, а решение 2 включает в себя копию проектов A и B.


Когда я создаю Решение 1, вот что должно произойти:

alt text


Когда я создаю Решение 2, вот что должно произойти:

alt text


Как я могу это сделать?

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

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

  • Может быть простым консольным приложением с параметром командной строки для указания «исходного решения», например:

    c:\Program Files\Library Syncronizer\LibSync.exe /solution:Solution 1
    
  • XML-файл, используемый для регистрации активных решений, содержащих библиотечные проекты. Возможный формат:

    <solutions>
      <solution>
        <name>Solution1</name>
        <path>c:\...\Projects\Solution 1</path>
      </solution>
      <solution>
        <name>Solution2</name>
        <path>c:\...\Projects\Solution 2</path>
      </solution>
      <!-- more solutions -->
    </solutions>
    
  • Программа будет делать следующее:

    • Читать в исходном решении
    • Определите, какие библиотечные проекты у него есть
    • Скопируйте папки для этих проектов в библиотеку
    • Перебрать каждое решение в файле XML (кроме исходного)
    • При необходимости скопируйте папки для всех проектов библиотеки
    • Возможно, может также произойти некоторая операция резервного копирования, на случай, если процесс синхронизации перезапишет что-то важное.

Это звучит относительно просто в концепции, но это может иметь серьезные непредвиденные последствия, о которых я не думаю. Надеюсь, кто-нибудь предупредит меня, если это произойдет:)


Обновление - Каков мой мотив для копирования папок проекта?

Одним словом - Контроль версий.

Если я храню проекты библиотек в отдельной папке и ссылаюсь на них только в своих различных решениях (вместо того, чтобы физически находить папки в папках моего решения), мой репозиторий управления версиями заканчивается тем, что не содержит исходного кода для моих проектов библиотеки , Итак, если я обновлю «три версии назад», и мне нужно будет внести небольшие изменения в один из моих библиотечных методов, кода там нет.

Мой обходной путь для этого заключается в добавлении тегов к ревизиям в хранилище моей библиотеки, которые говорят что-то вроде «Solution 1 - Version 2.5.3», но это довольно неуклюже. И все становится действительно неловким, если я работаю над «тремя версиями ранее» решения 1 и текущей версией решения 2. Теперь решение 2 будет указывать на старую версию проектов библиотеки, что делает невозможным потенциально работать и тестировать, пока я не закончу работать над старой версией Solution 1.

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

Здесь следует отметить, что я использовал Tortoise HG (Mercurial) для контроля версий.

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


Обновление 2

Прежде всего, просто записка. Я использую Mercurial (TortoiseHG) для контроля версий, а не SVN. Я мог бы измениться, если это абсолютно необходимо, но я действительно предпочитаю Mercurial.

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

alt text

Я по-прежнему преследую те же цели, однако:

  1. В последней версии каждого решения используется новейший код библиотеки
  2. Одно решение / заявка на репозиторий
  3. Каждый репозиторий содержит весь исходный код, включая библиотечные проекты
  4. Все максимально автоматизировано, чтобы минимизировать риск ошибок

Цель № 1 решается автоматически путем ссылки на библиотечные проекты вместо использования копий, а цель № 2 - просто вопрос о том, как я настроил свои репозитории, но цели № 3 и № 4 остаются неясными.

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

На данный момент я думаю, что хорошим решением может быть просто сохранение резервных копий проектов библиотеки в моих папках Solution. Когда я говорю «резервные копии», я имею в виду буквально. Я все еще буду ссылаться на проекты библиотеки - копии будут предназначены исключительно для того, чтобы весь исходный код попадал в мой репозиторий (цель № 3). Для достижения цели № 4 эти резервные копии можно автоматизировать с помощью события после сборки в студии.

Я приветствую ваши мысли по этому поводу.

Ответы [ 5 ]

3 голосов
/ 10 февраля 2010

Способ решения аналогичной проблемы - это то, что вы описываете в обновлении 2, но там, где вы предлагаете «резервные копии», мы используем клонов, и они являются неотъемлемой частью нашего рабочего процесса.

Мое решение.

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

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

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

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

Почему я так делаю?

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

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

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

Это рабочий процесс, который никогда не был бы возможен с традиционными VCS, такими как SourceSafe, но прекрасно работает с DVCS, такими как Hg.

Конкретные решения этих неуловимых целей.

Чтобы попытаться ответить на ваши неуловимые цели

0,3. Каждый репозиторий содержит весь исходный код, включая библиотечные проекты

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

0,4. Все максимально автоматизировано, чтобы минимизировать риск ошибок

Я делаю это с кучей пакетных файлов, которые я храню в каталоге своего приложения.

Например, данное приложение "_projects.bat" может содержать:

@echo off
@shift
set APPDIR=%CD%
cd ..\Library1
%0 %1 %2 %3 %4 %5 %6 %7 %8 %9

cd ..\Library2
%0 %1 %2 %3 %4 %5 %6 %7 %8 %9

cd ..\Library3
%0 %1 %2 %3 %4 %5 %6 %7 %8 %9

cd %APPDIR%
%0 %1 %2 %3 %4 %5 %6 %7 %8 %9

pause

Затем у меня есть пакетные файлы для выполнения полезных функций синхронизации, таких как проверка, какие файлы будут извлечены с помощью "__incoming.bat:

@echo off
call _projects hg incoming

и проверьте, что будет выдавлено с помощью __outgoing.bat:

@echo off
call _projects hg outgoing

Или фактически выполнить эти операции с "__push.bat":

@echo off
call _projects hg push

и "__pull.bat":

@echo off
call _projects hg pull

пока "__update.bat" обновляет все до последней версии (в той же ветке вам все равно придется явно обновляться вне текущей ветки):

@echo off
call _projects hg update

Одним из моих любимых файлов является "__ids.bat", который показывает, какие наборы изменений (и разветвленные) в настоящее время используются и, что важно, есть ли у них невыполненные изменения:

@echo off
call _projects hg id

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

Обратите внимание на то, что подчеркивания в именах файлов просто помещают их в верхнюю часть списков каталогов, чтобы их было легче найти. * 8' )

Будущие варианты.

В конце концов, я бы хотел полностью автоматизировать этот рабочий процесс с помощью суб-репо (чтобы состояние всего приложения и всех его библиотек записывалось в одном наборе изменений приложения), но пока оно становится довольно стабильным в Mercurial, интеграция с TortoiseHG не кажется приоритетом. Я не мог заставить инструмент THG commit делать что-нибудь полезное в прошлый раз, когда я его пробовал (около 0.8.3). Я действительно должен повторить тестирование с 0.9.3, но я не могу вспомнить какие-либо заметки о суб-репо в журналах изменений, поэтому оно того не стоит, если люди не скажут мне, что поддержка суб-репо THG была тихо добавлена.

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

Если кому-то захочется попробовать, я бы хотел увидеть ответ в этой теме. * 8' )

Берегите себя, надеюсь, это поможет,

Mark ..........

3 голосов
/ 17 января 2010

Подумайте, почему ваши Приложения должны работать с разными версиями библиотек. Если вы спроектировали свои библиотеки должным образом и убедитесь, что ничего не сломали при их обновлении (используйте непрерывную интеграцию и модульные тесты, а также тестирование всех зависимых проектов), то лучший (самый простой, самый чистый) подход в большинстве случаев заключается в все приложения запускаются на одной и той же версии библиотек. Я бы сказал, что если ваши Приложения не могут работать с одной и той же версией Библиотеки, это говорит о том, что ваши Библиотеки не спроектированы / не реализованы / не поддерживаются должным образом, и вам следует пересмотреть свой подход.

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

Я бы рекомендовал переместить проекты библиотеки в библиотеку. На вашей диаграмме показаны прикладные решения, создающие библиотечный код и помещающие его в библиотеку, а затем возвращающие файлы встроенной библиотеки обратно в проекты - двунаправленная копия, eek! Просто поместите библиотечные проекты в библиотеку и соберите библиотеку, а затем создайте ссылку на эту библиотеку из ваших проектов - однонаправленную копию. Вы можете подумать, что это означает, что вам придется создавать два решения (Библиотека и затем Приложение), но вы можете добавлять / удалять библиотечные проекты в своем приложении Solution, когда вам это нужно, поэтому такая компоновка не требует двухэтапного процесса сборки. Но логическое различие между библиотекой и приложением намного чище.

2 голосов
/ 17 января 2010

Это похоже на то, для чего нужна поддержка в репозитории в Mercurial. Если проект A и проект B и т. Д. Являются отдельными репозиториями, вы можете сделать их суб-репо в решениях 1 и 2. Файлы .hgsub в 1 и 2 сами по себе являются версионными и указывают на конкретные ревизии в A, B и C, так что вы всегда можете собрать с одной и той же версией в каждом решении, но вам не нужно держать их в режиме блокировки. Перенос изменений из решений в библиотеки становится простым и, при желании, ветвящимся.

Не позволяйте упоминанию "бета-версии 1.3" на этой вики-странице обмануть вас. Mercurial до версии 1.4.2 сейчас, а подпункты остаются такими, как есть.

0 голосов
/ 17 января 2010

Извините, я не прочитал весь текст на этой странице. НО! Краткий ответ: Visual Studio выполняет всю необходимую автоматизацию .

У нас похожая структура. Solution1, Solution2 и общая библиотека с несколькими проектами. Наша структура папок в SVN выглядит следующим образом:

\myRepository
            \Solution1
            \Solution2
            \CommonLibrary\
                          \Project1
                          \Project2
                          \Project3

Как видите, без копирования здесь. Оба решения просто сохраняют ссылку на ..\CommonLibrary\ProjectX.

После того, как я выполнил команду SVN-Update для репозитория, Visual Studio спросит меня: «ProjectX был изменен. Вы хотите перезагрузить его? Я нажимаю «да» и продолжаю кодирование.

PS: также посмотрите на это программное обеспечение http://svnnotifier.tigris.org/ Он может обновлять любое количество локальных копий хранилища автоматически (по таймеру) или щелчком мыши.

0 голосов
/ 16 января 2010

Я не уверен, что понимаю цель вашей "Библиотеки"?

Почему два решения на самом деле не ссылаются на один и тот же проект, а на копию?

Если цель состоит в том, чтобы иметь возможность работать с разными ветвями «Библиотеки», то то, что вы описываете, - это то, что обрабатывается программным обеспечением для контроля исходного кода, таким как SVN.

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

...