How can I get next Git commit by date? - windows

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>

Related

Extract numeric and non-numeric part from a string with WSO2

Thanks before. i want need help. I have simple process flow with wso2. The plan was validate and print string for alphabet and numeric. I can print both of them. but i think the formula was so much affort with that. i want find the simple way. i done try with regular expression. but when i try with that. i always get error result
My code :
<?xml version="1.0" encoding="UTF-8"?>
<api context="/split1" name="SplitAlphaNumber" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="POST">
<inSequence>
<property expression="//OperationValueRegex/Value" name="Value" scope="default" type="STRING"/>
<payloadFactory media-type="xml">
<format>
<OperationValueRegex xmlns="">
<Result1>$1</Result1>
<Result2>$2</Result2>
</OperationValueRegex>
</format>
<args>
<arg evaluator="xml" expression="translate(., translate($ctx:Value,'0123456789',''), '')"/>
<arg evaluator="xml" expression="translate(., translate($ctx:Value,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',''), '')"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>
Expected Result was like this
<OperationValueRegex>
<Result1>1234</Result1>
<Result2>Mario Naga</Result2>
</OperationValueRegex>
Sample Input from postman :
<OperationValueRegex>
<Value>Mario Naga 1234</Value>
</OperationValueRegex>
and actual output :
<OperationValueRegex>
<Result1>
1234
</Result1>
<Result2>
MarioNaga
</Result2>
</OperationValueRegex>
Please need suggestion with this. thanks
Here is a simpler way to achieve what you need. Make sure Xpath 2.0 is enabled in WSO2 Server.
Use the following two XPath expressions.
fn:tokenize($ctx:Value, ' ')[matches(., '\d+')] // Tokenize the String with space and extract the part with numeric values.
fn:replace($ctx:Value, ' \d+', '') //Replace the numeric part from the string
PLFactory Mediator
<payloadFactory media-type="xml">
<format>
<OperationValueRegex xmlns="">
<Result1>$1</Result1>
<Result2>$2</Result2>
</OperationValueRegex>
</format>
<args>
<arg evaluator="xml" expression="fn:tokenize($ctx:Value, ' ')[matches(., '\d+')]" xmlns:fn="http://www.w3.org/2005/xpath-functions" />
<arg evaluator="xml" expression="fn:replace($ctx:Value, ' \d+', '')" xmlns:fn="http://www.w3.org/2005/xpath-functions" />
</args>
</payloadFactory>
It seems you do a second translate to get rid of leading/trailing spaces. This messes up your values. Instead you can use normalize-space() function as follows, this gets you the desired output:
<api xmlns="http://ws.apache.org/ns/synapse" name="SplitAlphaNumber" context="/split1">
<resource methods="POST">
<inSequence>
<property name="Value" expression="//OperationValueRegex/Value" scope="default" type="STRING"/>
<payloadFactory media-type="xml">
<format>
<OperationValueRegex xmlns="">
<Result1>$1</Result1>
<Result2>$2</Result2>
</OperationValueRegex>
</format>
<args>
<arg evaluator="xml" expression="normalize-space(translate($ctx:Value,'0123456789',''))"/>
<arg evaluator="xml" expression="normalize-space(translate($ctx:Value,'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz',''))"/>
</args>
</payloadFactory>
<respond/>
</inSequence>
<outSequence/>
<faultSequence/>
</resource>
</api>

How to display Text on MSBuild only when ItemGroup Count > 0?

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.

Need to finding overlapping dates in XML code

I need help finding the overlapping dates in this XML code. I need to make sure that the End date is not less than or equal to the proceeding Start Date.
<Inventory>
<StatusApplicationControl Start="2019-07-18" End="2019-07-18" InvTypeCode="STDX" />
<InvCounts>
<InvCount CountType="2" Count="9" />
</InvCounts>
</Inventory>
<Inventory>
<StatusApplicationControl Start="2019-07-18" End="2019-07-19" InvTypeCode="STDX" />
<InvCounts>
<InvCount CountType="2" Count="8" />
</InvCounts>
</Inventory>
I have tried the following code.
<rule context="Inventory">
<report test="translate(StatusApplicationControl/#Start, '-', '') <= translate(preceding::Inventory/preceding::StatusApplicationControl/#End, '-', '')">The #Start="<value-of select="#Start"/>" and #End="<value-of select="#End"/>" dates are overlaping</report>
</rule>
I expect this message to be printed -
The Start="2019-07-18" is less than or equal to the End="2019-07-18" date
Any help is greatly appreciated!
It looks like the comments are not helping you.
The rule should be:
<rule context="Inventory">
<report
test="translate(StatusApplicationControl/#Start, '-', '')
<=translate(preceding::Inventory[1]/StatusApplicationControl/#End,'-','')"
>The #Start="<value-of select="#Start"/>" and #End="<value-of
select="preceding::Inventory[1]/StatusApplicationControl/#End"
/>" dates are overlaping</report>
</rule>
EDIT
This Schematron
<schema xmlns="http://purl.oclc.org/dsdl/schematron">
<pattern>
<title>Test dates</title>
<rule context="Inventory">
<assert
test="translate(StatusApplicationControl/#Start, '-', '')
> translate(preceding::Inventory[1]/StatusApplicationControl/#End,'-','')"
>The #Start="<value-of
select="StatusApplicationControl/#Start"
/>" and #End="<value-of
select="preceding::Inventory[1]/StatusApplicationControl/#End"
/>" dates are overlaping</assert>
</rule>
</pattern>
</schema>
With this input:
<root>
<Inventory>
<StatusApplicationControl Start="2019-07-18" End="2019-07-18" InvTypeCode="STDX" />
<InvCounts>
<InvCount CountType="2" Count="9" />
</InvCounts>
</Inventory>
<Inventory>
<StatusApplicationControl Start="2019-07-18" End="2019-07-19" InvTypeCode="STDX" />
<InvCounts>
<InvCount CountType="2" Count="8" />
</InvCounts>
</Inventory>
</root>
Output:
Pattern 'Test dates' Failed : The #Start="2019-07-18" and #End="2019-07-18" dates are overlaping.
Check in https://www.liquid-technologies.com/online-schematron-validator
Here is the SchemaTron rule that worked for me. The issue was passing preceding:: to the translate() function. When doing that I got a SchemaTron Exception.
<rule context="Inventory/StatusApplicationControl">
<report test="translate(#Start, '-', '') <= preceding::StatusApplicationControl/translate(#End, '-', '') ">The #Start="<value-of select="#Start"/>" and #End="<value-of select="#End"/>" dates are overlaping</report>
</rule>

Summary table with xForms

I have an xml like the following:
<table1>
<row>
<person>person1</person>
<value>10</value>
</row>
<row>
<person>person2</person>
<value>20</value>
</row>
<row>
<person>person1</person>
<value>5</value>
</row>
</table1>
<summaryTable>
<row>
<person>person1</person>
<value_total/>
</row>
<row>
<person>person2</person>
<value_total/>
</row>
</summaryTable>
With XForms 1 (there is no option to switch to XForms 2), using framework betterform, I want to calculate the values in the summary table, by doing the SUM of the rows in 'table1' that have the same person name. To do that I have the following binds:
<xf:bind id="bind_table1"
nodeset="table1" repeatableElement="row">
<xf:bind id="bind_head_table1" nodeset="head" />
<xf:bind id="bind_row_table1" nodeset="row">
<xf:bind id="bind_person" nodeset="person" type="xf:string" />
<xf:bind id="bind_value" nodeset="value" type="xf:integer" />
</xf:bind>
</xf:bind>
<xf:bind id="bind_summaryTable"
nodeset="summaryTable"
repeatableElement="row">
<xf:bind id="bind_head_summaryTable" nodeset="head" />
<xf:bind id="bind_row_summaryTable" nodeset="row">
<xf:bind id="bind_person_name" nodeset="person_name" type="xf:string" readonly="true"/>
<xf:bind id="bind_value_total" nodeset="value_total" type="xf:integer" readonly="true" calculate="SUM(//table1/row[person/text() = ../person_name/text()]/value)"/>
</xf:bind>
</xf:bind>
What I want to have at the end is the value_total for person1 = 15 and value_total for person2 = 20, but using this 'calculate' expression I'm getting 'NaN'. If I replace the calculate expression to compare with a literal String like:
<xf:bind id="bind_value_total" nodeset="value_total" type="xf:integer" readonly="true" calculate="SUM(//table1/row[person/text() = 'person1']/value)"/>
then I get as value_total 15 (the sum is correctly done). So it seems that the error is in the comparison expression person/text() = ../person_name/text() . Does someone have an idea about how should be the correct expression?
Thanks
Try the context() function in the calculate attribute to refer to the current node, like this:
<xf:bind nodeset="summaryTable/row/value_total" calculate="sum(//table1/row[person/text() = context()/../person/text()]/value)"/>
The context function gives you the current context node. If your bind references a nodeset with multiple nodes, it will be evaluated one time for every node, and that node is what context() returns.
It works for me with XSLTForms, maybe your version of betterForm supports it.

Passing Itemgroup between msbuild project

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>

Resources