a regex can't count the brace pairs
Absolutely true, but if git's using PCRE, those
aren't regexes in the technical sense, and here's some Perl that uses a "regex" to match the brace pairs:
http://stackoverflow.com/a/133771/8446 Git's use of PCRE is spotty. git-grep uses it (with the -P switch), but git-blame has no equivalent, and does not use PCRE. The simple test is to use an embedded modifier:
$ git grep '(?i)pauseexec' ../../omanalyze.cpp
$ git grep -P '(?i)pauseexec' ../../omanalyze.cpp
../../omanalyze.cpp:int pauseExec(int value)
../../omanalyze.cpp: exit(pauseExec(1));
../../omanalyze.cpp: exit(pauseExec(1));
../../omanalyze.cpp: return pauseExec(0);
../../omanalyze.cpp: return pauseExec ( 0 );
$ git blame -L '/pauseExec/,/}/' ../../omanalyze.cpp
8a714b87 (canuck 2015-05-15 16:10:54 +0000 37) int pauseExec(int value)
8a714b87 (canuck 2015-05-15 16:10:54 +0000 38) {
8a714b87 (canuck 2015-05-15 16:10:54 +0000 39) if (pauseAtExit) {
8a714b87 (canuck 2015-05-15 16:10:54 +0000 40) printf("hit return to exit...");
8a714b87 (canuck 2015-05-15 16:10:54 +0000 41) char buf[ 128 ];
8a714b87 (canuck 2015-05-15 16:10:54 +0000 42) if (fgets(buf, sizeof(buf) - 1, stdin));
8a714b87 (canuck 2015-05-15 16:10:54 +0000 43) }
$ git blame -L '/(?i)pauseexec/,/}/' ../../omanalyze.cpp
fatal: -L parameter '(?i)pauseexec' starting at line 1: No match
Part of the problem that Tony's facing is that
-L takes 2 parameters -- the start of the range, and the end of the range. Those are independent regex, so he can't use back references to match indent (
/^(\s*)funcName/,/^\1}/ won't work), nor would any fancy PCRE, even if it were available.
On first look, the
-L :<funcname> option seems like it's the answer:
$ git blame -L :'pauseExec' ../../omanalyze.cpp
8a714b87 (canuck 2015-05-15 16:10:54 +0000 37) int pauseExec(int value)
8a714b87 (canuck 2015-05-15 16:10:54 +0000 38) {
8a714b87 (canuck 2015-05-15 16:10:54 +0000 39) if (pauseAtExit) {
8a714b87 (canuck 2015-05-15 16:10:54 +0000 40) printf("hit return to exit...");
8a714b87 (canuck 2015-05-15 16:10:54 +0000 41) char buf[ 128 ];
8a714b87 (canuck 2015-05-15 16:10:54 +0000 42) if (fgets(buf, sizeof(buf) - 1, stdin));
8a714b87 (canuck 2015-05-15 16:10:54 +0000 43) }
[...]
8a714b87 (canuck 2015-05-15 16:10:54 +0000 46) }
8a714b87 (canuck 2015-05-15 16:10:54 +0000 47)
However,
-L :<funcname> doesn't understand indented definitions. For example, suppose the following code:
class fooImpl
{
[...]
static bool limitMemoryFootprint()
{
switch(m_platform) {
// [...]
}
}
[...]
}
Then looking for the
limitMemoryFootprint() method fails:
$ git blame -L :'limitMemoryFootprint' test.cc
fatal: -L parameter 'limitMemoryFootprint' starting at line 1: no match
Remove the indentation, and it works just fine.
I'd say that Tony's best bet is to figure out the start and end line numbers of the function outside of git, and use those rather than regex parameters to the
-L option (caution: line-noise ahead):
$ perl -ne'if(/pauseExec/){$a=$.;tr/{/{/||next}if($a){$b+=tr/{//;$b-=tr/}//;$b||exit print "$a,$.\n"}' ../../omanalyze.cpp
37,46
$ git blame -L 37,46 ../../omanalyze.cpp
8a714b87 (canuck 2015-05-15 16:10:54 +0000 37) int pauseExec(int value)
8a714b87 (canuck 2015-05-15 16:10:54 +0000 38) {
8a714b87 (canuck 2015-05-15 16:10:54 +0000 39) if (pauseAtExit) {
[...]
8a714b87 (canuck 2015-05-15 16:10:54 +0000 46) }