I have following Target:
<Target Name="RemoveUnusedCopiedfiles" AfterTargets="CopyFilesToOutputDirectory" Condition="'$(Configuration)' == 'Release'">
<ItemGroup>
<FileToDelete Include="#(_SourceItemsToCopyToOutputDirectory -> '$(TargetDir)\%(FileName)%(Extension)')" Condition="%(Extension) == '.pdb' OR %(Extension) == '.xml'"/>
</ItemGroup>
<Delete Files="#(FileToDelete)"/>
<Message Text="Deleted Files #(FileToDelete -> '%(FullPath)', ', ')"
Importance="high"/> // Problem Here I need only show Deleted Files if FileToDelete.Count > 0
<!-- Remove other unused files -->
<Delete Files="$(MSBuildProjectDirectory)\$(MSBuildProjectName).nuspec"/>
</Target>
I don't know exactly how to make above <Message> only appeard if FileToDelete variable Count > 0? How to do that in MSBuild?
I always get this line: Image are here
Is there something in MSBuild collection value: i.e: Condition = "#(FileToDelete.Count > 0)"
You can check it like this:
<Message Text="Deleted Files #(FileToDelete -> '%(FullPath)', ', ')"
Importance="high" Condition="'#(FileToDelete)' != ''"/>
The #(...), in a "string context", will expand to the items, delimited by a semicolon. Or an empty string, if the ItemGroup is empty.
Related
In a script (msbuild) on a windows machine, I have the SHA1 of a commit.
What is the correct git command, to get the "next" (by date) commit SHA1 in the same branch?
Take a look at this example log from TortoiseGit:
In my script I currently have the 4b60a7e87762f421ddeee4ea0282a99c5db20e4a. Now I need a command to get c0fb4c86c354cfe32c6d0f1753958ab60db7e086.
I ended up writing a Custom MSBuild-Task which finds the predecessor. I post it in case it might come in handy for someone else.
Based on the comments of joanis I ended up looking in the git log for the next commit. So in my msbuild-script I now have a target which finds the next git commit and executes a specific target TargetToExecuteForNextGitCommit and sets the property CurrentCommitHash to the hash value of the next git commit. So this looks like:
<Target Name="DoTargetForNextGitCommit">
<!-- 6. Nachfolger vom aktuellen Commit finden -->
<!-- 6.a Tag des aktuellen Commits finden. Damit die Anzahl der zu durchsuchenden Commits einschränken.
Denn ich suche ja nur nach Commits, die danach kamen. -->
<Exec Command="git log --format=%25%25cd --date=iso-strict -n 1 $(CurrentCommitHash)"
WorkingDirectory="$(GitRepoDir)"
ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="GitCommitTimestamp"/>
</Exec>
<Message Text="Commit-Zeitstempel: $(GitCommitTimestamp)"/>
<!-- 6.b Git-Log holen, in eine ItemGroup packen, den Index des Elements finden, das meinen Hash hat
und dann den Nachfolger holen und dessen hash finden -->
<!-- 6.b.i Git-Log holen -->
<Exec Command="git log --date-order --format=%25%25H --after=$(GitCommitTimestamp) origin/master"
WorkingDirectory="$(GitRepoDir)"
ConsoleToMSBuild="true">
<Output TaskParameter="ConsoleOutput" PropertyName="GitCommitHashesAfterCommitDay"/>
</Exec>
<ItemGroup>
<GitCommitHashesAfterCommitDayEntries Include="$(GitCommitHashesAfterCommitDay)"/>
</ItemGroup>
<!-- 6.b.ii Nachfolger holen-->
<GetNextCommit Items="#(GitCommitHashesAfterCommitDayEntries)" CurrentCommitHash="$(CurrentCommitHash)">
<Output TaskParameter="NextCommitHash" PropertyName="NextCommitHashProperty"/>
</GetNextCommit>
<Message Text="Nächster Commit: $(NextCommitHashProperty)" />
<!-- 7. Wenn es einen Nachfolger gibt, dann beginne mit diesem wieder bei 1. -->
<MSBuild Projects="$(MSBuildThisFile)"
Targets="$(TargetToExecuteForNextGitCommit)"
Properties="CurrentCommitHash=$(NextCommitHashProperty)"
Condition=" '$(NextCommitHashProperty)' != '0' "/>
</Target>
<UsingTask TaskName="GetNextCommit" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v12.0.dll">
<ParameterGroup>
<Items ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
<CurrentCommitHash ParameterType="System.String" Required="true" />
<NextCommitHash ParameterType="System.String" Output="true" Required="false" />
</ParameterGroup>
<Task>
<Using Namespace="System.Linq"/>
<Code Type="Fragment" Language="cs">
<![CDATA[
var hashes = Items.Select(i => i.ItemSpec).ToList();
var currentCommitIndex = hashes.IndexOf(CurrentCommitHash);
if (currentCommitIndex < 1)
{
NextCommitHash = "0";
}
else
{
var nextCommitIndex = currentCommitIndex - 1;
NextCommitHash = hashes[nextCommitIndex];
}]]>
</Code>
</Task>
</UsingTask>
I am trying to get the attribute tags within accessory tag to be line items of a CSV file
I have tried to iterate using map function but im just getting one value at a time.What i want is there are two Accesory Type tag in this XML i want their respective attribute tags to become each line item in the CSV
<Accessory Type="Panel">
<PartNumber>9021447</PartNumber>
<Attribute Name="DescCode">Operating Panel, White/PI White, Low E SmartSun Tempered Glass</Attribute>
<Attribute Name="Mark_ID">41424</Attribute>
<Attribute Name="Order_Quantity">1</Attribute>
<Attribute Name="QUOTE_QUANTITY">1</Attribute>
<Attribute Name="Quote_Quantity_Extended">1</Attribute>
<Attribute Name="MarkName">0001</Attribute>
<Attribute Name="US_ENERGY_STAR_CLIMATE_ZONE">Northern</Attribute>
<Attribute Name="SubUnitID">1</Attribute>
<Attribute Name="AW_Control_2">47AoYY</Attribute>
<Attribute Name="ReferenceID">3</Attribute>
<Attribute Name="OrderPONum"/>
</Accessory>
<Accessory Type="Screen">
<PartNumber>2505930</PartNumber>
<Attribute Name="Total_Pre_Price_in_USD">208.70</Attribute>
<Attribute Name="Total_Price_in_USD">208.700</Attribute>
<Attribute Name="QUOTE_QUANTITY">1</Attribute>
<Attribute Name="Quote_Quantity_Extended">1</Attribute>
<Attribute Name="DescCode">Insect Screen, Gliding, White</Attribute>
<Attribute Name="Mark_ID">41424</Attribute>
<Attribute Name="Order_Quantity">1</Attribute>
</Accessory>
I have tried to make the attributes under accessory tag to become line items.
Expected output:
9021447|Operating Panel, White/PI White, Low E SmartSun Tempered Glass|41424
//and in the next line
25005930|208.70|1 //and so on
This is the code that i have tried
%dw 2.0
output application/json
---
payload.m2oFile.m2oOrder.Unit.*Accessory map (value, index) -> {
(index) : value.*Attribute filter($.#Name == "MarkID"),
(index) : value.*Attribute filter($.#Name == "PRODTYPE"),
(index) : value.*Attribute filter($.#Name == "UNIT_CODE")
}
Try with this approach..
%dw 2.0
output application/csv header=false
---
(payload.a.*Accessory map {
PN: $.PartNumber,
($.*Attribute map {
(($$) : $) if (isEmpty($) == false)
})
}
)
Should give you the output as follows:
PS: i had to add "a" as the root to the xml as otherwise the xml would not be well formed..
How can I insert another XML element into an XML file I'm creating with Builder::XmlMarkup? e.g., something like
xml = Builder::XmlMarkup.new( :indent => 4 )
xml.content
xml.common do
xml.common_field1 do
// common_field1 content
end
xml.common_field2 do
// common_field 2 content
end
end
xml.custom do
xml.insert!(<XML element>)
end
end
Where <XML element> looks something like
<elements>
<element>
// element content
</element>
<element>
// element content
</element>
<elements>
and the final output looks like
<content>
<common>
<content1>
<!-- content1 -->
</content1>
<content2>
<!-- content2 -->
</content2>
</common>
<custom>
<elements>
<element>
<!-- element content -->
</element>
<element>
<!-- element content -->
</element>
</elements>
</custom>
</content>
I've tried using the << operator but that doesn't unfortunately doesn't maintain formatting.
<< is exactly what you need:
xml.custom do |custom|
custom << '<XML element>'
end
Rubydocs doesn't seem to work, so here's the link to the source code: https://github.com/jimweirich/builder/blob/master/lib/builder/xmlbase.rb#L104
Let's say I have several file nodes with a property called foo. In Jackrabbit the xpath query I use to find those nodes by a property value is as follows:
/jcr:root/content/*[jcr:uuid='9b3d22fc-2354-49a6-afd0-9b672ae5a553']//file[foo = 10] order by #score
An oversimplified and raw representation of my repository as XML would look like this:
<content>
<formNode jcrUuid="9b3d22fc-2354-49a6-afd0-9b672ae5a553">
<year>
<month>
<day>
<hour>
<min>
<file foo="4"></file>
<file foo="10"></file>
</min>
</hour>
</day>
<day>
<hour>
<min>
<file foo="10"></file>
</min>
<min>
<file foo="5"></file>
</min>
</hour>
<hour>
<min>
<file foo="6"></file>
</min>
</hour>
</day>
</month>
</year>
</formNode>
</content>
Now. How can I find all the file nodes with the maximum value of foo? Does anyone know how to do this either by using xpath or JCR_SQL2?
I've tried the following queries without success:
Returns all the file nodes under the provided jcr:uuid
/jcr:root/content/*[jcr:uuid='9b3d22fc-2354-49a6-afd0-9b672ae5a553']//file[not(../file/foo > foo)] order by #score
Throws an Exception
jcr:root/content/*[jcr:uuid='9b3d22fc-2354-49a6-afd0-9b672ae5a553']//file[not(//file/foo > foo)] order by #score
Exception:
javax.jcr.query.InvalidQueryException: Unsupported root level query node: org.apache.jackrabbit.spi.commons.query.RelationQueryNode#8fedc
I've also tried the function fn:max. But AFAIK this is a XPATH 2.0 feature, which is not supported by JackRabbit 2.2.13, and I'm forced to use this version of JackRabbit.
How can i pass an itemgroup between msbuild project using MSbuild task. I have an Msbuild task as given below
<Target Name ="test">
<MSBuild Projects="New.proj" Targets="mytarget"
Properties="Itemproperty=#(Item->'%(FullPath)')">
</MSBuild>
</Target>
Where 'Item' is the itemgroup.But iam getting an error as below.
error MSB4012: The expression "Itemproperty=#(Item->'%(FullPath)')" cannot be used in this context. Item lists cannot beconcatenated with other strings where an item list is expected. Use a semicolonto separate multiple item lists.
Thanks
Can you "flatten" it into a big long (single) string?
example:
<PropertyGroup>
<MySuperLongString>#(MyIncludeFiles->'"%(fullpath)"')</MySuperLongString>
</PropertyGroup>
Here are some more "options"
<Message Text="The below items are good when you need to feed command line tools, like the console NUnit exe. Quotes around the filenames help with paths that have spaces in them. "/>
<Message Text="I found this method initially from : http://pscross.com/Blog/post/2009/02/22/MSBuild-reminders.aspx Thanks Pscross! "/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="Flat list, each file surrounded by quotes, with semi colon delimiter: "/>
<Message Text=" #(MyIncludeFiles->'"%(fullpath)"')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="Flat list, each file surrounded by quotes, no comma (space delimiter): "/>
<Message Text=" #(MyIncludeFiles->'"%(fullpath)"' , ' ')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="Flat list, each file surrounded by quotes, with comma delimiter: "/>
<Message Text=" #(MyIncludeFiles->'"%(fullpath)"' , ',')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="List of files using special characters (carriage return)"/>
<Message Text="#(MyIncludeFiles->'"%(fullpath)"' , '%0D%0A')"/>
<Message Text=" "/>
<Message Text=" "/>
Full example below:
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="AllTargetsWrapper" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="AllTargetsWrapper">
<CallTarget Targets="FunWithFilesTask" />
</Target>
<PropertyGroup>
<WorkingCheckout>.</WorkingCheckout>
</PropertyGroup>
<!-- ===================================================== -->
<!--
See:
http://msdn.microsoft.com/en-us/library/ms164313.aspx
*Identity Value for the item specified in the Include attribute.
*Filename Filename for this item, not including the extension.
*Extension File extension for this item.
*FullPath Full path of this item including the filename.
*RelativeDir Path to this item relative to the current working directory.
*RootDir Root directory to which this item belongs.
RecursiveDir Used for items that were created using wildcards. This would be the directory that replaces the wildcard(s) statements that determine the directory.
*Directory The directory of this item.
AccessedTime Last time this item was accessed.
CreatedTime Time the item was created.
ModifiedTime Time this item was modified.
-->
<Target Name="FunWithFilesTask">
<ItemGroup>
<MyExcludeFiles Include="$(WorkingCheckout)\**\*.doesnotexist" />
</ItemGroup>
<ItemGroup>
<MyIncludeFiles Include="$(WorkingCheckout)\**\*.*" Exclude="#(MyExcludeFiles)" />
</ItemGroup>
<PropertyGroup>
<MySuperLongString>#(MyIncludeFiles->'"%(fullpath)"')</MySuperLongString>
</PropertyGroup>
<Message Text="MySuperLongString=$(MySuperLongString)"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="The below items are good when you need to feed command line tools, like the console NUnit exe. Quotes around the filenames help with paths that have spaces in them. "/>
<Message Text="I found this method initially from : http://pscross.com/Blog/post/2009/02/22/MSBuild-reminders.aspx Thanks Pscross! "/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="Flat list, each file surrounded by quotes, with semi colon delimiter: "/>
<Message Text=" #(MyIncludeFiles->'"%(fullpath)"')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="Flat list, each file surrounded by quotes, no comma (space delimiter): "/>
<Message Text=" #(MyIncludeFiles->'"%(fullpath)"' , ' ')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="Flat list, each file surrounded by quotes, with comma delimiter: "/>
<Message Text=" #(MyIncludeFiles->'"%(fullpath)"' , ',')"/>
<Message Text=" "/>
<Message Text=" "/>
<Message Text="List of files using special characters (carriage return)"/>
<Message Text="#(MyIncludeFiles->'"%(fullpath)"' , '%0D%0A')"/>
<Message Text=" "/>
<Message Text=" "/>
</Target>
</Project>