Is it possible to rename a file during copy with Nuspec files node - nuget

I am currently working on changing our codebase to use Nuget. As part of the process the copying of ressources to the output directory should be moved from postbuild events in the projects to the files tag in the .nuspec file.
For the particular project the ressource was called Resources.resx and is renamed to something more specific during the copy (yes I know great programming - not mine and not my place to change it).
Is it possible to change the filename using the file node in nuspec or do I need to keep a postbuild in this case?
My attemp of renaming it with the target property fails:
< file src="foo/bar.resx" target="foo/foobar.resx"/>
creates the following output:
"foo/foobar.resx/bar.rex"
I found a familiar problem on github but it was rejected due to being posted on a dead branch and not trying to rename a file but change its type.
https://github.com/NuGet/Home/issues/2019
Thanks for the help

This functionality is not built into NuGet. The only conceivable way to do this would be to implement a powershell script (install.ps1) that would handle the rename of both the file and the csproj.

Late to the party, but this looks like it could work:
From: https://learn.microsoft.com/en-us/nuget/reference/nuspec
Renaming a content file in the package
Source file:
ie\css\style.css
.nuspec entry:
<file src="ie\css\style.css" target="Content\css\ie.css" />
Packaged result:
content\css\ie.css
Edit:
I found this post (https://stackoverflow.com/a/45601252/182888) where it says:
Note: The File extension in src and target must match or the specified target will be treated like a directory.
So keep that in mind or it might trip you up.

Related

Deliver temporary build-time assets with nuget

What is the proper way of delivering temporary build-time assets using nuget?
I am making a nuget package with a single file, which dependent projects require during the build phase. I would like the content of the file to be copied to obj\$(Configuration) folder inside a dependent project before proceeding with the rest of the build. Of course, the obj folder is temporary, so I would like my file to be copied there again as part of the next build if obj gets cleared out.
I tried contentFiles approach described here. This takes care of packaging my file inside nupkg file, but I was unable to set it up so that my file gets delivered (and re-delivered) to obj\$(Configuration).
You're looking for NuGet's MSBuild extensibility. Unfortunately it means you'll need to learn a bit about MSBuild if you don't already know it. I recommend running msbuild -bl or dotnet build -bl, which will create a msbuild.binlog file, which you can view with the msbuild structured log viewer.
One option is to have a target that creates the file in the intermediate output directory at an appropriate time (probably need to use BeforeTargets). You could use the Inputs and Outputs attributes to have msbuild do incremental build checks and skip copying when it doesn't need to, possibly making the build a little faster.
However, unless the file is has dynmanic content, copying the file is a waste. it's just going to be included as an item in another part of the build process. So, if it's static content, you could just create the relevant item in your targets file from your package's extracted directory, and then it's just as good as if it was copied to the intermediate output directory, without wasted time and duplicated disk space.

TDS File Replacement

I want to deploy some front end assets to the local web root of a site using file replacement. I can't seem to get it to work with a relative path in the target location field though. Is it possible to do this though tds or should I use a post build event instead?
The reason these assets aren't included in a project is that they are part of a third party solution but we still want this tracked in source control to try to make the project setup easier.
Most developer machines will be set up the same way for this project with the same file structure but I think it's a little more flexible if I can make the target a relative path so I don't need to worry about differences like drive letters and such.
The folder structure is as follows:
repo
folderToCopy
sitecore
webroot
I have tried the following using ..'s based on what tds changed my source location to be while using the "Make selected Source Location relative" option (changed it from an absolute path to ..\folderToCopy\):
../../Sitecore/Website
/../../Sitecore/Website
..\..\Sitecore\Website
\..\..\Sitecore\Website
From my understanding, TDS does the file replacement based on the files published from the associated Website project.
You can then have relative replacements such as the following:
<Replacement Include=".\assets\folderToCopy\myFile.txt">
<TargetPath>.\assets\targetFolder\myFile.txt</TargetPath>
<IsFolder>False</IsFolder>
<IsRelative>True</IsRelative>
</Replacement>
I have not been able to successfully get TDS to use the file replacement with files that are in source control but not in the project.
My suggestion would be to set up a build event that will copy these files to the correct location, or to create a nuget feed for them and pull them in as nuget references.

EntityDeploySplit error - Microsoft.Data.Entity.Build.Tasks.dll missing

After a clean Windows reformat and installing Visual Studio 2013, trying to build a project with database-first Entity Framework edmx files yields the following error:
The "EntityDeploySplit" task could not be loaded from the assembly
C:\Program Files
(x86)\MSBuild\12.0\bin\Microsoft.Data.Entity.Build.Tasks.dll. Could
not load file or assembly 'file:///C:\Program Files
(x86)\MSBuild\12.0\bin\Microsoft.Data.Entity.Build.Tasks.dll' or one
of its dependencies. The system cannot find the file specified.
Confirm that the declaration is correct, that the assembly
and all its dependencies are available, and that the task contains a
public class that implements Microsoft.Build.Framework.ITask.
Is there some way to install this separately? What is this assembly included with by default?
UPDATE: This also manifests itself when looking for the EntityClean task. I'm inclined to think that it checks the bin first, since another developer who was running it fine tried a clean / rebuild and then this started showing up.
I found the accepted answer to be a little confusing, below are the steps that worked for me.
Open C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Data.Entity.targets in notepad.
Alter the UsingTask elements to:
<UsingTask TaskName="EntityDeploySplit"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
<UsingTask TaskName="EntityDeploy"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
<UsingTask TaskName="EntityDeploySetLogicalNames"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
<UsingTask TaskName="EntityClean"
AssemblyFile="Microsoft.Data.Entity.Build.Tasks.dll" />
I ran into this problem and was able to fix it as I have described below. Your paths and variables may be different.
I found that when my project builds it points to this target file:
C:\Program Files (x86)\MSBuild\12.0\Bin\Microsoft.Data.Entity.targets
That target file appears to just be a placeholder. There is an Import element, in that file, that points to $(MSBuildFrameworkToolsPath)\Microsoft.Data.Entity.targets which runs the target file located at that path. I searched registry and found that MSBuildFrameworkToolsPath is a registry entry with the value of C:\Windows\Microsoft.NET\Framework\v4.0.30319\
I went to the targets file that was referenced and search for the UsingTask element that was specified in my exception. Inside the UsingTask element, the AssemblyFile attribute was pointed to $(MSBuildBinPath)\Microsoft.Data.Entity.Build.Tasks.dll. I searched the registry and found that the MSBuildBinPath registry entry was pointed to c:\Windows\Microsoft.NET\Framework\v3.5\
I'm not sure why it was pointed to that, maybe a Framework or Visual Studio installation didn't clean it up. Finally, I changed all my UsingTask elements' AssemblyFile attributes to:
$(MSBuildFrameworkToolsPath)\Microsoft.Data.Entity.Build.Tasks.dll
I used the same variable that was in the MSBuild Bin target file.
Hope this helps.
I give a lot of credit to Andy Mahaffey for his answer, without it I would not have found what I did.
I followed along his line of research but didn't like the idea of just changing the UsingTasks' attributes. I opened up the "C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Data.Entity.targets" file and I found the first thing it says after the opening Project element is this comment:
<!-- This .targets file can be used by updating Microsoft.Common.targets to
include the line below (as the last import element just before the end project tag)
<Import Project="$(MSBuildBinPath)\Microsoft.Data.Entity.targets" Condition="Exists('$(MSBuildBinPath)\Microsoft.Data.Entity.targets')"/>
-->
I followed it's suggestion and presto, problems solved.
I hope this helps!
TLDR
Paste the line below as the last element before the tag in the following file. C:\Windows\Microsoft.NET\Framework\v4.0.30319\Microsoft.Common.targets
<Import Project="$(MSBuildBinPath)\Microsoft.Data.Entity.targets" Condition="Exists('$(MSBuildBinPath)\Microsoft.Data.Entity.targets')"/>
In my case, I had accidentally created two copies of one of my .edmx files, one in a subfolder, where I didn't notice it. Once I deleted the extra one, everything was fine.

Best practices for using Hg with Grails?

What should I check in/not check in? Since many of the files are sometimes auto-generated I'm not entirely sure how to handle this using version control...does it have something to do with tags?
For instance in ANT, I know not to check-in my target/bin directories...but Grails adds another level of confusion to this...since some of code is generated and some of it is not.
(It may become clearer as I go...but it seems to be that there needs to be some way of being able to tell what was just generated and what was modified by a developer so that it needs to be placed in version control)
Here's the .hgignore directory I've got on my most recent grails project (with a couple of project specific things taken out):
syntax: glob
out
target
logs
*.iml
.idea
*.iws
*.war
workspace.xml
lib/build
lib/compile
lib/runtime
lib/test
~$*
stacktrace.log
*.tmproj
*.launch
reports/
*.orig
*.zip
.DS_Store
*/.DS_Store
web-app/WEB-INF/classes
cobertura.ser
The generated code in Grails should be placed under version control. It's not secondary executable code that is generated by the build process like class files, but instead is code that is part of your source. The generated code is intended to be just a starting point for your application and will most likely be modified at some point anyway.
Also check this:
http://www.grails.org/Checking+Projects+into+SVN
and this:
https://stackoverflow.com/questions/4201578

Dynamically add files to visual studio deployment project

I've been desperately looking for the answer to this and I feel I'm missing something obvious.
I need to copy a folder full of data files into the TARGETDIR of my deployment project at compile time. I can see how I would add individual files (ie. right click in File System and go to Add->File) but I have a folder full of data files which constantly get added to. I'd prefer not to have to add the new files each time I compile.
I have tried using a PreBuildEvent to copy the files:
copy $(ProjectDir)..\Data*.* $(TargetDir)Data\
which fails with error code 1 when I build. I can't help but feel I'm missing the point here though. Any suggestions?
Thanks in advance.
Graeme
Went to this route.
Created a new project (deleted the default source file Class1)
Added the files/folders necessary to the project.
Added the project as project output in the installer, choosing the option content files.
This removes the complexity of having to zip/unzip the files as suggested earlier.
Try
xcopy $(ProjectDir)..\Data\*.* $(TargetDir)Data /e /c /i [/f] [/r] /y
/e to ensure tree structure fulfilment (use /s if you want to bypass empty folders)
/c to continue on error (let the build process finish)
/i necessary to create the destination folder if none exists
/y assume "yes" for overwrite in case of previously existing files
[optionnal]
/f if you wanna see the whole pathes resulting from the copy
/r if you want to overwrite even previously copied read-only files
The method is simpler on the project than on files, yes. Beside, on files, it copies only the modified/missing files on each build but forces you to maintain the project on each data pack modification. Depends on the whole data size and the variability of your data pack.
Also beware the remaining files if you remove some from your data pack and rebuild without emptying your target folder.
Good luck.
I solved the problem by a workaround:
Add a build action of packaging entire directory (could be filtered) to a ZIP file.
Add a reference to an empty ZIP file to deployment project.
Add a custom action to deployment project to extract the ZIP to destination folder.
It's simple and stable.
Your error is probably because your path has spaces in it and you don't have the paths in quotes.
ex copy "$(ProjectDir)..\Data*.*" "$(TargetDir)Data\"
I need to do a similar thing. Thinking a custom action...
I found a different workaround for this. I added a web project to my solution that points at the data directory I want included in the deployment project. The web project automatically picks up any new files in the data directory and you can refer to the project content in the deployment project.