web-dev-qa-db-fra.com

Configuration d'un dossier de packages de nuget commun pour toutes les solutions lorsque certains projets sont inclus dans plusieurs solutions

J'utilise NuGet pour récupérer des paquets à partir de sources de paquets externes et internes, ce qui est très pratique. Mais je me suis rendu compte que les packages sont stockés par défaut pour chaque solution, ce qui est très frustrant lorsque certains projets avec des références NuGet sont inclus dans plusieurs solutions. Ensuite, les références sont modifiées en un autre dossier de package de solutions qui peut en réalité ne pas être disponible pour un autre développeur ou une autre machine de construction.

J'ai vu qu'il existe des moyens de signaler un emplacement de package commun (peut-être au niveau racine du projet, nous utilisons le contrôle de source TFS) avec la version 2.1 de NuGet, voir notes de version . J'utilise NuGet v2.7

Mais j'ai essayé d'ajouter des fichiers nuget.config sans en voir le moindre effet. Les packages sont toujours stockés dans le dossier de la solution. Y a-t-il quelque chose que j'ai oublié? Il semble y avoir différentes structures du nœud xml à ajouter au fichier nuget.config, en fonction de qui répond à cette question: Schwarzie suggère sur un autre thread Stackoverflow :

<settings>
  <repositoryPath>..\..\[relative or absolute path]</repositoryPath>
</settings>

Les notes de publication de NuGet 2.1 (voir lien ci-dessus) suggèrent ce format: 

<configuration>
  <config>
    <add key="repositoryPath" value="..\..\[relative or absolute path]" />
  </config>
</configuration>

Je ne sais pas lequel de ceux-ci, ni aucun, ni les deux ne fonctionneront à la fin. J'ai essayé les deux au niveau de la solution. Le fichier nuget.config peut-il être placé au niveau racine du projet TFS ou doit-il être dans le répertoire de la solution? Il semble que NuGet lit et applique les paramètres de ces fichiers dans un certain ordre. Par conséquent, il serait judicieux de les ajouter à plusieurs niveaux, où un fichier nuget.config au niveau de la solution en remplacerait un au niveau racine du projet TFS. Cela peut-il être clarifié?

Dois-je supprimer tous les packages installés avant que ces références fonctionnent? J'aimerais beaucoup que quelqu'un puisse vous fournir des instructions détaillées permettant de passer d'une utilisation de nuget spécifique à une solution à un dossier de packages commun contenant des projets appartenant à plusieurs les solutions peuvent trouver leurs paquets de nuget requis.

121
Mats Isaksson

J'ai une situation similaire avec des sources de paquetages externes et internes avec des projets référencés dans plusieurs solutions. Je viens de travailler avec l'une de nos bases de code aujourd'hui et cela semble fonctionner avec les postes de travail de développeurs et notre serveur de build. Le processus ci-dessous a ce scénario en tête (même s’il ne devrait pas être difficile de s’adapter pour avoir le dossier des paquets communs ailleurs).

  • Code base
    • Projet A
    • Projet B
    • Projet c
    • Solutions
      • Solution 1
      • Solution 2
      • Solution 3
      • Paquets (c'est le commun partagé par toutes les solutions)

Réponse mise à jour à partir de NuGet 3.5.0.1484 avec Visual Studio 2015 Update 3

Ce processus est un peu plus facile maintenant que lorsque je l’avais abordé à l’origine et que je pensais qu’il était temps de le mettre à jour. En général, le processus est le même avec moins d'étapes. Le résultat est un processus qui résout ou fournit ce qui suit:

  • Tout ce qui doit être associé au contrôle de code source est visible et suivi dans la solution.
  • L'installation de nouveaux packages ou la mise à jour de packages à l'aide du gestionnaire de packages dans Visual Studio utilisera le chemin de référentiel correct.
  • Après la configuration initiale, pas de piratage des fichiers .csproj
  • Aucune modification du poste de travail du développeur (le code est prêt à être utilisé à la caisse)

Il y a certains inconvénients potentiels à connaître (je ne les ai pas encore expérimentés, YMMV). Voir la réponse et les commentaires de Benol ci-dessous.

Ajouter NuGet.Config

Vous voudrez créer un fichier NuGet.Config à la racine du dossier\Solutions \. Assurez-vous qu'il s'agit d'un fichier codé UTF-8 que vous créez. Si vous ne savez pas comment procéder, utilisez le menu Fichier-> Nouveau-> Fichier de Visual Studio, puis choisissez le modèle de fichier XML. Ajoutez à NuGet.Config ce qui suit:

<?xml version="1.0" encoding="utf-8"?>
<configuration>  
  <config>
    <add key="repositoryPath" value="$\..\Packages" />
  </config>
</configuration>

Pour le paramètre repositoryPath, vous pouvez spécifier un chemin absolu ou relatif (recommandé) à l'aide du jeton $. Le jeton $ est basé sur l'emplacement du NuGet.Config (le jeton $ est relatif à un niveau en dessous de l'emplacement du NuGet.Config). Donc, si j'ai\Solutions\NuGet.Config et que je veux\Solutions\Packages, je devrai spécifier $\..\Packages comme valeur.

Ensuite, vous voudrez ajouter à votre solution un dossier de solution appelé quelque chose comme "NuGet" (clic droit sur votre solution, Ajouter-> Nouveau dossier de solution). Les dossiers de solution sont des dossiers virtuels qui n'existent que dans la solution Visual Studio et ne créeront pas de dossier réel sur le lecteur (vous pouvez référencer des fichiers à partir de n'importe où). Cliquez avec le bouton droit de la souris sur le dossier de votre solution "NuGet", puis sur Ajouter-> Article existant et sélectionnez\Solutions\NuGet.Config.

Cela s'explique par le fait que cela est visible dans la solution et devrait permettre de s'assurer qu'il est correctement engagé dans votre contrôle de code source. Vous souhaiterez peut-être effectuer cette étape pour chaque solution de votre base de code participant à vos projets partagés.

En plaçant le fichier NuGet.Config dans\Solutions\au-dessus des fichiers .sln, nous tirons parti du fait que NuGet parcourra la structure de dossiers de manière récursive à partir du "répertoire de travail en cours" à la recherche du fichier NuGet.Config à utiliser. Le "répertoire de travail en cours" signifie deux choses différentes ici, l'une est le chemin d'exécution de NuGet.exe et l'autre l'emplacement du fichier .sln.

Changer de dossier de paquets

Tout d'abord, je vous recommande vivement de parcourir chacun de vos dossiers de solution et de supprimer tous les dossiers\Packages\existants (vous devez d'abord fermer Visual Studio). Cela permet de voir plus facilement où NuGet place votre dossier\Packages\récemment configuré et garantit que tout lien vers un dossier\Packages\incorrect échouera et pourra ensuite être corrigé.

Ouvrez votre solution dans Visual Studio et lancez une reconstruction complète. Ignorez toutes les erreurs de construction que vous allez recevoir, cela est attendu à ce stade. Cela devrait toutefois lancer la fonctionnalité de restauration du paquet NuGet au début du processus de construction. Vérifiez que votre dossier\Solutions\Packages\a été créé à l’emplacement souhaité. Si ce n'est pas le cas, vérifiez votre configuration.

Maintenant, pour chaque projet de votre solution, vous voudrez:

  1. Cliquez avec le bouton droit sur le projet et sélectionnez Décharger le projet.
  2. Cliquez avec le bouton droit sur le projet et sélectionnez Modifier votre-xxx.csproj.
  3. Recherchez les références à\packages\et mettez-les à jour.
    • La plupart d'entre elles seront des références <HintPath>, mais pas toutes. Par exemple, WebGrease et Microsoft.Bcl.Build auront des paramètres de chemin distincts qui devront être mis à jour.
  4. Enregistrez le fichier .csproj, puis cliquez avec le bouton droit de la souris sur le projet et sélectionnez Recharger le projet.

Une fois que tous vos fichiers .csproj ont été mis à jour, lancez un autre fichier Rebuild All et vous ne devriez plus avoir d'erreur de génération concernant les références manquantes. À ce stade, vous avez terminé et configurez NuGet pour utiliser un dossier Packages partagé.

À partir de NuGet 2.7.1 (2.7.40906.75) avec VStudio 2012

Tout d’abord, il faut garder à l’esprit que nuget.config ne contrôle pas tous les paramètres de chemin d’accès dans le système de paquetage nuget. C'était particulièrement déroutant à comprendre. Spécifiquement, le problème est que msbuild et Visual Studio (appelant msbuild) n'utilisent pas le chemin dans nuget.config mais le remplacent plutôt dans le fichier nuget.targets.

Préparation de l'environnement

Premièrement, je parcourrais le dossier de votre solution et supprimerais tous les\packages\dossiers existants. Cela vous aidera à vous assurer que tous les packages sont installés visiblement dans le bon dossier et à découvrir les références de chemins incorrects dans vos solutions. Ensuite, je m'assurerais que vous avez la dernière extension Visual Studio de nuget installée. Je voudrais également m'assurer que vous avez le dernier nuget.exe installé dans chaque solution. Ouvrez une invite de commande et accédez à chaque dossier $ (SolutionDir)\.nuget \, puis exécutez la commande suivante:

nuget update -self

Définition du chemin de dossier de paquetage commun pour NuGet

Ouvrez chaque $ (SolutionDir)\.nuget\NuGet.Config et ajoutez les éléments suivants dans la section <configuration>:

<config>
    <add key="repositorypath" value="$\..\..\..\Packages" />
</config>

Remarque: Vous pouvez utiliser un chemin absolu ou relatif. Gardez à l'esprit que si vous utilisez un chemin relatif avec $, il est relatif à un niveau inférieur à l'emplacement de NuGet.Config (croyez qu'il s'agit d'un bogue).

Définition du chemin de dossier de package commun pour MSBuild et Visual Studio

Ouvrez chaque $ (SolutionDir)\.nuget\NuGet.targets et modifiez la section suivante (notez que pour les non-Windows, une autre section se trouve en dessous):

<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
    <!-- Windows specific commands -->
    <NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
    <PackagesConfig>$([System.IO.Path]::Combine($(ProjectDir), "packages.config"))</PackagesConfig>
    <PackagesDir>$([System.IO.Path]::Combine($(SolutionDir), "packages"))</PackagesDir>
</PropertyGroup>

Mettre à jour PackagesDir to be

<PackagesDir>$([System.IO.Path]::GetFullPath("$(SolutionDir)\..\Packages"))</PackagesDir>

Remarque: GetFullPath résoudra notre chemin relatif en un chemin absolu.

Restauration de tous les paquets de nugets dans un dossier commun

Ouvrez une invite de commande et allez à chaque $ (SolutionDir)\.nuget et exécutez la commande suivante:

nuget restore ..\YourSolution.sln

À ce stade, vous devez avoir un seul dossier\packages\dans votre emplacement commun et aucun dans l'un de vos dossiers de solution. Si non, alors vérifiez vos chemins.

Fixation des références de projet

Ouvrez chaque fichier .csproj dans un éditeur de texte, recherchez les références à\packages et mettez-les à jour avec le chemin correct. La plupart d'entre elles seront des références <HintPath>, mais pas toutes. Par exemple, WebGrease et Microsoft.Bcl.Build auront des paramètres de chemin distincts qui devront être mis à jour.

Construisez votre solution

Ouvrez votre solution dans Visual Studio et lancez une construction. S'il se plaint de paquets manquants devant être restaurés, ne supposez pas que le paquet est manquant et doit être restauré (une erreur peut être trompeuse). Cela pourrait être un mauvais chemin dans l’un de vos fichiers .csproj. Vérifiez cela avant de restaurer le paquet.

Vous avez une erreur de construction à propos des paquets manquants?

Si vous avez déjà vérifié que les chemins dans vos fichiers .csproj sont corrects, vous avez deux options à essayer. Si cela résulte de la mise à jour de votre code à partir du contrôle de code source, vous pouvez essayer d'extraire une copie vierge, puis de la construire. Cela a fonctionné pour l'un de nos développeurs et je pense qu'il y avait un artefact dans le fichier .suo ou quelque chose de similaire. L'autre option consiste à forcer manuellement la restauration d'un package à l'aide de la ligne de commande du dossier .nuget de la solution en question:

nuget restore ..\YourSolution.sln
138
Vermis

Au lieu de définir un emplacement de package commun pour tous les projets, il est également possible de modifier HintPath dans le projet comme suit:

<HintPath>$(SolutionDir)\packages\EntityFramework.6.1.0\lib\net40\EntityFramework.dll</HintPath>

Dans la plupart des cas, il n'y aura que quelques paquets dans un projet partagé, vous pouvez donc le changer facilement.

Je pense que c'est une meilleure solution, lorsque vous branchez du code, lorsque vous définissez un référentiel commun, vous devez modifier le chemin relatif, dans cette solution, vous n'avez pas besoin de le faire.

37
Adam Wyżgoł

Mon expérience en essayant cela avec la dernière version de NuGet (2.7) et VS2012:

  • Supprimer le dossier .nuget (sur le disque et dans la solution)
  • Placez un fichier NuGet.Config dans un dossier parent commun à toutes les solutions.
  • Supprimer tous les dossiers de packages existants
  • Parcourez tous les fichiers csproj et modifiez HintPaths pour qu'il pointe vers le nouvel emplacement.
  • Profit

Dans mon cas, je voulais mettre tous les paquets dans .packages, donc mon NuGet.Config ressemblait à celui ci-dessous. 

 <?xml version="1.0" encoding="utf-8"?>
 <configuration>
   <config>
     <add key="repositorypath" value=".packages" />
   </config>
 </configuration>

Notez qu'il y a quelques "choses étranges" qui peuvent arriver, mais je pense qu'elles sont supportables: 

  • Si vous "mettez à jour" un paquet à partir d'une solution, il supprimera rapidement l'ancienne version de votre dossier de paquets (il ne peut pas savoir si vous avez une autre solution qui pointe là-bas). Cela ne me dérange pas beaucoup, car l'autre solution ne fait que restaurer, le cas échéant.
  • Si vous essayez d'ajouter un package à partir d'un clic droit sur la solution, si le package est déjà présent dans une autre solution, il verra qu'il est là et vous indiquera la "coche verte" au lieu du bouton "installer". J'installe généralement à partir d'un clic droit sur le projet, donc cela ne me dérange pas du tout.

Disclaimer : Je viens d'essayer cela aujourd'hui, je n'ai aucune expérience à long terme pour le sauvegarder!

20
Benjol

J'ai la version 2.8.50926 de NuGet avec VS 2013. Vous n'avez pas besoin d'utiliser plusieurs fichiers nuget.config, ni d'utiliser des structures de répertoires complexes. Il suffit de modifier le fichier par défaut situé ici:

%APPDATA%\Roaming\NuGet\NuGet.Config

Voici le contenu de mon dossier:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <config>
    <add key="repositoryPath" value="C:\Projects\nugetpackages" />
  </config>
  <activePackageSource>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  </activePackageSource>
</configuration>

Tous les packages sont donc placés dans le dossier "C:\Projects\nugetpackages", où que se trouve la solution.

Dans toutes vos solutions, supprimez simplement les dossiers "packages" existants. Générez ensuite votre solution et NuGet restaurera automatiquement les packages manquants dans le nouveau répertoire centralisé que vous avez spécifié.

18
Matthieu

Déjà, il n'est pas nécessaire de modifier nuget.targets. Il a été corrigé dans nuget 2.8 ( http://nuget.codeplex.com/workitem/2921 ). Il vous suffit de définir repitoritorypath.

8
daniel

J'ai concocté un package NuGet qui convertit de manière transparente toutes les références NuGet d'un projet au format relatif à $ (SolutionDir). Pour ce faire, il utilise la transformation XSLT au moment de la compilation, vous n'avez donc pas besoin de pirater votre fichier de projet à la main. Vous pouvez mettre à jour vos paquets librement, cela ne cassera rien.

https://www.nuget.org/packages/NugetRelativeRefs

Ou si vous utilisez Visual Studio 2015 Update 3, vous pouvez simplement migrer vos références de package au format project.json comme décrit ici: https://oren.codes/2016/02/08/project-json-all- les choses

3
Oleg Tarasov

À partir de Visual Studio 2013 Update 4 et de la version du gestionnaire de packages de nuggets> 2.8.5 ...

Créez un fichier nuget.config à la racine du référentiel.

contenu du fichier:

<configuration>
  <config>
    <add key="repositoryPath" value="packages" />
  </config>
  <packageSources>
    <add key="nuget.org" value="https://www.nuget.org/api/v2/" />
  </packageSources>
</configuration>

Cela fera en sorte que tous les paquets iront dans leur dossier au niveau du fichier nuget.config de votre.

Maintenant, vous pouvez choisir chaque console de nuget .sln avec la commande 'update-package -reinstall'

Si vous avez plusieurs référentiels au même niveau et que vous voulez partager le même dossier de paquetage entre eux, essayez d'utiliser un moyen de créer un dossier. 

 <add key="repositoryPath" value="..\packages" />

Mais de cette façon, vous faites en sorte que la référence des packages de nuget csproj pointe vers un dossier situé en dehors du chemin de votre référentiel.

3
user

Pour toute solution significative, les réponses ci-dessus seront insuffisantes. Tout simplement, une structure d’espace de travail TFS complexe avec des chemins relatifs, des branchements, des projets partagés, etc. différents rend un référentiel central unique impossible. 

Utiliser ($ SolutionDir) est un pas dans la bonne direction, mais coder manuellement le fichier csproj avec ($ SolutionDir) deviendrait assez fastidieux dans une base de code contenant des centaines de paquets mis à jour régulièrement un nouveau chemin relatif). Que se passe-t-il si vous devez exécuter Update-Package -Reinstall.

Il existe une excellente solution appelée NugetReferenceHintPathRewrite . Il automatise l'injection de ($ SolutionDir) dans HintPaths juste avant la construction (sans modifier réellement le fichier csproj). J'imagine qu'il pourrait facilement être intégré à des systèmes de construction automatisés 

2
gravidThoughts

Il vous suffit de créer un lien matériel/de paquets vers l’emplacement partagé souhaité. Ensuite, votre projet ne sera pas interrompu pour les autres utilisateurs n'ayant pas d'emplacement de paquetage particulier. 

Ouvrez une invite de commande en tant qu'administrateur et utilisez-la.

mklink /prefix link_path Target_file/folder_path
2
user803469

Mise à jour de mon expérience avec Nuget 2.8.3. C'était relativement simple. Tout a été fait enabled package restore à partir du clic droit sur la solution. Edited NuGet.Config et a ajouté les lignes suivantes:

  <config>
    <add key="repositorypath" value="..\Core\Packages" />
  </config>

Ensuite, la solution a été reconstruite. Tous les packages ont été téléchargés dans le dossier souhaité et les références mises à jour automatiquement. J'ai fait la même chose pour tous mes autres projets, où seuls les packages incrémentiels ont été téléchargés et les packages existants ont été référencés. Par conséquent, un référentiel de paquet commun pour tous les projets a été défini.

Voici une procédure étape par étape pour activer la restauration de package.

http://blogs.4ward.it/enable-nuget-package-restore-in-visual-studio-and-tfs-2012-rc-to-building-windows-8-metro-apps/

2

Résumé succinct pour ceux sur VS 2013 professional avec NuGet Version: 2.8.60318.667

Voici comment vous dirigeriez les packages vers un chemin relatif au dossier .nuget:

<configuration>
  <config>
    <add key="repositoryPath" value="../Dependencies" />
  </config>
</configuration>

Par exemple, si votre solution (fichier .sln) réside dans C:\Projects\MySolution, lorsque vous activez la restauration du package NuGet, le dossier .nuget est créé comme suit: C:\Projects\MySolution.nuget et les packages sont téléchargés. dans un répertoire comme celui-ci: C:\Projects\MySolution\Dependencies

NOTE: Pour une raison inconnue, chaque fois que je mets à jour "repositoryPath", je dois fermer et rouvrir la solution pour que les modifications prennent effet.

1
Sudhanshu Mishra

pour ceux qui utilisent Paket en tant que gestionnaire de paquets, il existe une option auto-symlink pour votre fichier de dépendances:

storage: symlink

btw: le paket tire profit de la pépite

référence: https://fsprojects.github.io/Paket/dependencies-file.html

Si vous souhaitez modifier le moins possible, vous pouvez simplement nettoyer les sous-répertoires régulièrement avec un script. c'est à dire. Le comportement par défaut de Nuget est de copier des fichiers d'un emplacement global vers un dossier de packages local. Supprimez-les ensuite.

0
sgtz