Pull to refresh

NuGet — качаем пакеты из интернета в процессе сборки

Reading time 3 min
Views 18K
UPD: Метод, аналогичный использованному здесь включен в поставку NuGet 1.6. Соответственно статья устарела.

Вот что мне всегда нравилось в джаве, так это Maven. Один файл со списком всего нужного, и никаких бинарников в репозитории. Когда появился NuPack, я решил — ура, вот оно, счастье пришло на нашу улицу. Но не тут то было. NuPack представлял удобный интерфейс для работы с пакетами… но без возможности нормально вкрутится в процесс сборки.

Поковырял я его тогда, посмотрел, но так реальной пользы и не увидел. Не больно большая помощь — качать ручными powershell-командами пакеты поименно. Ну да, удобнее, чем скачивать фиг знает откуда, да еще руками references добавлять, но ведь мне это далеко не каждый день нужно. В общем, игра не стоит свеч.

Но в один прекрасный день я понял, что с папкой Shared\Bin в моем сорц-контроле нужно что-то делать, ибо распухла она уже неимоверно. Решил глянуть я, не изменилось ли что-нибудь с NuPack-ом, который уже NuGet-ом стал именоваться? Нет, воз и дальше там.

Но у nuget.exe появилась интересная фича...
Если передать ему в качестве параметра файл «packages.config», в котором NuGet хранит список пакетов, установленных в данный проект, то он скачает все пакеты указанные в нем!

Дело техники

1) Создаем NuGet.Targets, который будем включать в наши проекты:
<?xml version="1.0" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
 <PropertyGroup>
  <BuildDependsOn>
   _InsallNuGetPackages;$(BuildDependsOn)
  </BuildDependsOn>
 </PropertyGroup>

 <Target Name="_InsallNuGetPackages">
  <Exec Command="$(MSBuildThisFileDirectory)\NuGet install $(ProjectDir)packages.config -o $(SolutionDir)Packages" />
 </Target>
</Project>


* This source code was highlighted with Source Code Highlighter.

Кладем его в сорц-контрол, он будет запускать NuGet перед каждым билдом. Относительно размещения NuGet-а: можно положить exe-шку в сорц-контрол рядом с target-ом, можно — просто добавить в path. Первый вариант, как по мне, удобней, хотя и менее кошерен. Если вам больше по душе заставлять всех сотрудников ставить Nuget.exe в Path — просто уберите $(MSBuildThisFileDirectory).
… Не забудьте о билд-серверах;)

2) Добавляем в проект NuGet пакеты.
3) Добавляем руками в *.*proj-файл:
<Import Project="$(SolutionDir)\Где\там\ваши\таржеты\NuGet.Targets" />

* This source code was highlighted with Source Code Highlighter.

Собственно все, пакеты будут вытаскиваться автоматом при билде. И только в том случае, если их еще нет — что хорошо.

А что, если...

… у меня в проекте используются бинарники, который нет на nuget.org? Не проблема. Создадим свой фид. Можно использовать MyGet, но создать на своем сервере по-моему даже проще:
1) Создаем новый Empty Web Application Project
2) Ставим на него пакет NuGet.Server
3) Паблишим.

Все, готово. Можно немного подчистить, потому что публикуется мусор… Ну как обычно. В опубликованном проекте будет папка Packages, куда собственно и складываем наши пакеты.

Готовим гарнир пакеты.

Это тоже несложно. nuget.exe вам в помощь.
По очереди:
1) nuget spec имя.пакета сгенерирует файл с расширением nuspec, содержащий шаблон манифеста пакета. Подправляем, он тривиален, разберетесь сами :)
2) Кладем наш nuspec в пустую папочку, создаем рядом lib, кладем в него нашу dll.
Запускаем nuget pack имя.пакета.nuspec, который сгенерит файл пакета.
3) Заливаем полученный пакет на сервер, в вышеупомянутую папку Packages.

Относительно папочки lib: файлы, найденные в ней, будут добавлены в References в импортирующем проекте. И только так. Это не было четко описано в документации, так что понадобилось поэкспериментировать.

Завершающий штрих

Итак, у нас готов сервер с пакетами, нужно прикрутить его к студии и билд-процессу. В студии — опять таки без проблем:
Tools->Library Package Manager->Package Manager Settings, выбрать Package Sources, добавить свой. Да что это я собственно — если уж вы до этого места дочитали, то разберетесь.
Билд процесс: честно говоря, я надеялся, что NuGet будет хранить в Package-файлах и путь откуда качать. Но нет, он к таким мелочам не опускается. Придется добавлять параметры для nuget.exe… Помните, я вынес его запуск в отдельный файл? Много чести для одной строки, правда? Нет, неправда. Вот сейчас нам это пригодится (как пригодилось мне, чтобы не лазить по 30 отдельным проектам). Изменяем строчку с exec-ом на следующую:
<Exec Command="NuGet install $(ProjectDir)packages.config -o $(SolutionDir)Packages -Source nuget.example.com/nuget -Source go.microsoft.com/fwlink/?LinkID=206669" />

* This source code was highlighted with Source Code Highlighter.

Порядок источников именно такой — в случае чего можно будет подменить какую-то версию из оффициального репозитория своей, пропатченой (у меня например так с AjaxControlToolkit-ом).

… Поздравляю, теперь можно спокойно удалять монстра Shared\Bin, коммитить и наслаждатся чистотой в сорц-контроле.
Tags:
Hubs:
+29
Comments 14
Comments Comments 14

Articles