0

Pivotal Tracker can parse git commits and change ticket status accordingly. I am writing a PHP script that executes post-commit. It searches the commit message and if it finds the right Pivotal Ticket reference it posts it to the PT api. I'm going a bit nuts trying to figure out the regex.

Currently I have:

preg_match('/^\[#([0-9]{1,16})\]/', $commit['message'], $matches);

So the simplest example of a commit passes:

[#12345678] Made a commit

But what I need to pass are the following:

1: [finished #12345678] Made a commit //'fixed', 'complete', or 'finished' changes the status
2: I made a commit [#12345678] to a story //Can occur anywhere in the commit
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Scotty
  • 204
  • 1
  • 11
  • Take off the anchor `^` because your reference doesn't start at the beginning of the string. Maybe you want `\[(?:(?:finished|fixed|complete) )?)#([0-9]{1,16})\]` – chris85 Jul 09 '17 at 05:33
  • Are there any occurrences where a string is before the `#` inside the bracketed expression and it is NOT `finished`, `complete`, or `fixed`? Do you want to capture only the hashtag prefixed number substring, or do you want the leading word when it exists? Please include any "gotcha" strings that need to be avoided. Please clarify your expected result so that we can offer a truly refined solution. The better your question, the higher quality our response can be. – mickmackusa Jul 09 '17 at 07:47
  • Are there any bracketed expressions that shouldn't match? – mickmackusa Jul 09 '17 at 07:53

2 Answers2

0
$string = '2: I made a commit [#12345678] to a story
1: [finished #12345678] Made a commit
3: [fixed #12345678] Made a commit
4: [complete #12345678] Made a commit';

$m = [];
$regex = '/.*\[(finished|fixed|complete)?\s*#(\d+)\]/';

preg_match_all($regex,$string,$m); 

echo '<pre>';
print_r($m);
echo '</pre>';

Should give you

Array
(
[0] => Array
    (
        [0] => 2: I made a commit [#12345678]
        [1] => 1: [finished #12345678]
        [2] => 3: [fixed #12345678]
        [3] => 4: [complete #12345678]
    )

[1] => Array
    (
        [0] => 
        [1] => finished
        [2] => fixed
        [3] => complete
    )

[2] => Array
    (
        [0] => 12345678
        [1] => 12345678
        [2] => 12345678
        [3] => 12345678
    )

)

As you can see the () in the regex expression act as groups which stores the results in an array $m

$m[0] -> stores complete match 
$m[1] -> stores first group () 
$m[2] -> stores second group () 

I think safest way to do this is to process one commit at a time, but this example is just showing you the use cases in the question.

user1599755
  • 149
  • 1
  • 6
0

The sample inputs are:

I made a commit [#12345678] to a story
[finished #12345678] Made a commit
[fixed #12345678] Made a commit
[complete #12345678] Made a commit

Based on our regex pattern, only the numerical portion is targeted.

To write the best/most efficient pattern to accurately match your input strings, do not use capture groups -- use \K.

/\[[^#]*#\K\d{1,16}/   #just 24 steps

Demo Link


If you need to ensure that the before the #numbers comes either: [nothing], finished, fixed, or complete then this is as refined as I can make it:

/\[(?:fixed ?|finished ?|complete ?)?#\K\d{1,16}/    #59 steps

Demo Link

...this is the same effect as the previous pattern, only condensed slightly:

/\[(?:fi(?:x|nish)ed ?|complete ?)?#\K\d{1,16}/    #59 steps

Demo Link


If these patterns do not satisfy your actual requirements for any reason, please leave a comment and edit your question. I will adjust my answer to create a most-efficient accurate answer for you.

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
  • This is great. Your first example seems to work, and allows me to pass any commit that matches the basic pattern and lets the Pivotal API figure out what to do with it. Thanks!! – Scotty Jul 09 '17 at 12:57