NugetFileCustomTool

Topics: General
Mar 19, 2013 at 4:03 PM
Edited Mar 19, 2013 at 4:19 PM
@dotnetjunky

Just started on the work for getting nuget to set and call custom tools
http://nuget.codeplex.com/SourceControl/network/forks/Antix/NugetFileCustomTool

based on our discussion on http://nuget.codeplex.com/workitem/2202

I am focussing on getting it working for .settings files with an eye on all other file types which need the same

I am at the point where I would like to call the CustomToolSetter from inside the VsProjectSystem.AddFileToProject but will need to inject it in through a new constructor via the VsProjectSystemFactory

Do you have a preference on how I should do this? Or are you happy to have a look when I've had a crack at it?

Looking at it, the easiest by far would be a single concrete dependency to VsProjectSystem
Mar 19, 2013 at 4:41 PM
Edited Mar 19, 2013 at 4:50 PM
Actually, there's a lot of change down there and I need information which is up in IPackageFile for overriding the convention settings

So was looking in the ProjectSystemExtensions.AddFiles seems to be closer to what I need

I would only like to run the custom tool on newly added files, do you have any suggestions on that?

Could IProjectSystem.AddFile return true/false?
Mar 20, 2013 at 5:30 PM
What do you want to run the custom tool? If you set the CustomTools attribute to the file, VS will automatically run it for you. Am I missing something?
Mar 20, 2013 at 6:30 PM
Btw, while we're at this, I think we can support other attributes too, not just Custom Tool. How about adding support for the Custom Tool Namespace, Copy To Output Directory and Build Action?

Maybe we can allow the package author to set the attribute name and attribute value himself, instead of limiting to these 4 attributes. What do you think?
Mar 21, 2013 at 9:29 AM
Edited Mar 21, 2013 at 11:31 AM
Hi

VS wont run the customtool if you just add the file and set the property, you'll get compile failures if you are referencing anything from the (not) generated file.

But its easy enough to do, and that's in place

The architecture at the top will just run list of components, the components are given the IPublishFile, Path and the ProjectSystem so they can do what ever they need

I have a CustomTool setting component which will do this particular job

Yes I think we can extend it further
Mar 21, 2013 at 6:46 PM
Can you describe the schema of the nuspec that you're modifying to support this feature?
Mar 21, 2013 at 7:02 PM
Edited Mar 21, 2013 at 7:02 PM
Well that was my next task, but I am off on holidays for a few days, and then back to work, so might slow progress a bit

Firstly
The components for .settings files can use defaults and info from the settings file its-self, the SettingsSingleFileGenerator is the default one for a new file in vs, and the namespace can be found in the xml

I hoped .resx would be the same, but the namespace is not stored in the xml
So, will be looking at this again..

Anyway I was thinking (but not got too far), as far as the changes to the nuspec to allow for extension would be something like
<file src="x\y.thing" target="content">
    <property name="customtool" value="ThingGenerator" />
    <property name="customtoolnamespace" value="x" />
</file>
that way you can put any old thing in, and the property set in vs

What do you think?
Mar 21, 2013 at 8:22 PM
That looks good. The only thing is that src can accept wild card to include multiple files. When nuget.exe pack command creates the package, these information are lost.

In your implementation, I guess you have to read the .nuspec file embedded inside the .nupkg to retrieve the property values, right?
Mar 21, 2013 at 8:44 PM
Yes, I need to confirm what is in the IPackageFile on add, but I think so, and if so, it would read it first before add files begins.

This would set up the component with a list of matcher+process so after the actual files is added it is matched to the processes to be run on it.

Also, I suspect matching is not just against the file name, in some cases it may have to open the actual file to determine which process to be run, not sure though, but the design allows this in any case.
Apr 6, 2013 at 1:47 PM
Going with a more generic approach, where by adding properties to a file element will update a file added to VS.
I have forked again and this commit shows the changes to the nuspec schema to support this

https://nuget.codeplex.com/SourceControl/network/forks/Antix/NuGetFileProperties/changeset/9f1c4333b9d3e4369e0337d45224a72356e4755c

I have wrapped the property elements in a collection element in-line with other collections, so an example would be
<files>
    <file src=""my.txt"" target=""content"">
      <properties>
        <property name=""propName"" value=""propValue"" />
      </properties>
    </file>
</files>
Changes in this commit
  1. nuspec.xsd to include the above
  2. ManifestFile object to include a Properties property and added child classes
  3. ManifestSchemaUtility now contains a new version (v6)
  4. ManifestTestFileProperties contains tests to check expected function
Would you give it a quick review to check I haven't missed anything

I'll get on with the rest in the meantime
Apr 6, 2013 at 3:20 PM
Found a problem, the embedded nuspec does not contain the original files element
Should I add this to the PackageBuilder.WriteManifest method?
Apr 6, 2013 at 3:39 PM
This commit adds the ManifestFiles property to IPackage
https://nuget.codeplex.com/SourceControl/network/forks/Antix/NuGetFileProperties/changeset/4e63703c4d877d46006a291ec857e49fb5e1c36d

I can see another route to consider for this information.

Adding Properties to the File element may mean that the property data is repeated in the nuspec, so when you have a files collection like this
<files>
     <file src="my.txt" target="content/folder1" />
     <file src="myoyther.txt" target="content/folder2" />
</files>
If you wanted to set a property on all text files you'd need to do it in two places

Or you could do it as a separate element from file altogether
<files>
     <file src="my.txt" target="content/folder1" />
     <file src="myoyther.txt" target="content/folder2" />
</files>
<properties>
     <property file="*.txt" name="customtool" value="mycustomtool" />
</properties>
So, as the files are added, if the match the file pattern, the property is set

What do you think?
Apr 6, 2013 at 6:21 PM
I prefer to keep it simple. Let's go with the original design first. If people complain about repeating the information, we can add the <properties> section later. I don't want us to start with complicated design up front.
Jul 9, 2013 at 3:05 PM
Hi donetjunky

Firstly, sorry about the silence, finishing a contract

I have nearly finished this bit of work, all the components are in place and unit tested
I would like to put in some higher level, even integration tests and would appreciate your help on this

Would you be available for a code review in the next few days?
Would you be OK with a Skype screen share?

this is the repo I have been working in
https://nuget.codeplex.com/SourceControl/network/forks/Antix/NugetProjectFileProcessing

Ant
Jul 9, 2013 at 11:51 PM
Hi, fell free to send a pull request whenever you're ready. I can review and comment directly on the pull request.

If you have any question, you can post directly here.
Aug 26, 2013 at 8:50 PM
Hi -

Was this change ever made/approved? I just tried to use it and it does not look like it is part of the schema. Having properties on a per-file basis would be great to have.

-Raymond
Aug 29, 2013 at 4:38 PM
This feature hasn't yet been implemented. It's slated for NuGet 2.8.
May 11, 2014 at 10:05 PM
Very interesting and useful tips I think.I read step by step this informations and help me so much.Thank you for this great informations

jocuri cu barbie
Dec 12, 2014 at 10:35 PM
This doesn't seem to be implemented in 2.8 either. I could really use this capability. I need to set several metadata properties on some installed files including CustomTool and BuildAction. I'm trying to hack something with the VS DTE and I can get close but having a heck of time setting the BuildAction because its values are numeric and I haven't found a way to determine the numeric value of the build actions I've added via my package.