How do I generate an MsBuild itemList from another item list based on the current item's directory name?
i'm taking a list of files *.config
and copying them to a list of directories. The directories are relative to a path C:\branches\
have a name and then the name.UnitTest.
so the copy looks like this without being refactored/batched:
<Target Name="CopyClientConfigs">
<ItemGroup>
<ClientConfigDestinati开发者_运维技巧ons Include="$(LocalSourcePath)\Module1\Module1.UnitTest\;
$(LocalSourcePath)\Module2\Module2.UnitTest\;
$(LocalSourcePath)\CommonControls\Module3\Module3.UnitTest\;
$(LocalSourcePath)\Administration\Module4\Module4.UnitTest\;
$(LocalSourcePath)\IndividualControls\Configuration\Module5\Module5.UnitTest\" />
<ClientConfigs
Include="$(ClientConfigPath)\*.config"
Exclude="$(ClientConfigPath)\P*.config" >
</ClientConfigs>
</ItemGroup>
<Copy
SourceFiles="@(ClientConfigs)"
DestinationFolder="%(ClientConfigDestinations.FullPath)"
/>
What I want is to be able to use this ItemGroup
<ItemGroup>
<MyModules Include="$(LocalSourcePath)\Module1;
$(LocalSourcePath)\Module2;
$(LocalSourcePath)\CommonControls\Module3;
$(LocalSourcePath)\Administration\Module4;
$(LocalSourcePath)\IndividualControls\Configuration\Module5"
/>
So the task would be like
Copy
SourceFiles="@(ClientConfigs)"
DestinationFolder="%(ClientConfigDestinations.FullPath)\*.UnitTest\"
/>
Or better
Copy
SourceFiles="@(ClientConfigs)"
DestinationFolder="%(ClientConfigDestinations.FullPath)\%(ClientConfigDestinations.NameOnly).UnitTest\"
/>
How do I refactor or properly batch this operation?
If I read your question right, I think you are trying to do a cross-product copy: copy all items in one ItemGroup to all the folders in a different group.
I actually have a neat target that I use to do this, as I hate the way TeamBuild puts all the binaries into a single folder - I want projects to be able to specify that their output is a "bundle" and that the output will also be copied to one or more locations.
To do this, I have two itemgroups: BundleFiles (which is the set of files that I want to copy) and BundleFolders which are the set of folders that I want to copy to.
<ItemGroup>
<BundleOutDir Include="FirstFolder;SecondFolder" />
<BundleFiles Include="file1;file2" />
</ItemGroup>
My target then contains two tasks like this:
<ItemGroup>
<FilesByDirsCrossProduct Include="@(BundleFiles)">
<BundleOutDir>%(BundleOutDir.FullPath)</BundleOutDir>
</FilesByDirsCrossProduct>
</ItemGroup>
This creates an uber item group containing a cross product of files by folders.
The copy is then pretty simple:
<Copy SourceFiles="@(FilesByDirsCrossProduct)"
DestinationFiles="@(FilesByDirsCrossProduct -> '%(BundleOutDir)\%(Filename)%(Extension)' ) "
SkipUnchangedFiles="true" />
This then copies the files to the folder specified within their meta data.
My target is actually a little more clever in that I can declare that bundles will go to sub folders and/or I can rename a file during the copy through meta data, but that's a different story
<Target Name="CopyClientConfigsBatched" Outputs="%(MyModules.FullPath)">
<Message Text="@(MyModules -> '%(FullPath)\%(FileName).UnitTest')"/>
<ItemGroup>
<ClientConfigs
Include="$(ClientConfigPath)\*.config"
Exclude="$(ClientConfigPath)\P*.config" >
</ClientConfigs>
</ItemGroup>
<Copy SourceFiles="@(ClientConfigs)" DestinationFolder="@(MyModules -> '%(FullPath)\%(FileName).UnitTest')"
SkipUnchangedFiles="true"/>
</Target>
target batching seems to have done it!
精彩评论