git diff, svn diff でヘッダにラベルを避けて関数名を出したい

# 対象

* Subversion : 1.9.3
* Git : 2.7.4
* C言語のソースファイル

# 問題

`git diff` や `svn diff` で各差分のヘッダ (hunk-header?) に以下のように関数名も出せる。

```diff
@@ -2,7 +2,7 @@ void func1() {
```

しかし、以下のようにラベルが出てしまうことがある。

```diff
@@ -21,5 +21,5 @@ ERROR:
```

ラベルは避けて関数名を出したい。

# サンプルファイル

以下の sample.c の差分で試す。

```c:sample.c(変更前)
void func1() {
    //
    //
    //
    printf("bar\n");
}

void func2(char *s) {
    //
    //
    //
    if (s == NULL) {
        goto ERROR;
    }
    printf("'%s'\n", s);
    return;
    //
    //
    //
ERROR:
    //
    //
    //
    printf("Error!\n");
}
```

```c:sample.c(変更後)
void func1() {
    //
    //
    //
    printf("BAR\n");
}

void func2(char *s) {
    //
    //
    //
    if (s == NULL) {
        goto ERROR;
    }
    printf("%s\n", s);
    return;
    //
    //
    //
ERROR:
    //
    //
    //
    printf("error!\n");
}
```

# Subversion

内蔵の diff だとラベルが出てしまう。

```bash
svn diff -x -p
```

```diff
Index: sample.c
===================================================================
--- sample.c	(リビジョン 3)
+++ sample.c	(作業コピー)
@@ -2,7 +2,7 @@ void func1() {
     //
     //
     //
-    printf("bar\n");
+    printf("BAR\n");
 }
 
 void func2(char *s) {
@@ -12,7 +12,7 @@ void func2(char *s) {
     if (s == NULL) {
         goto ERROR;
     }
-    printf("'%s'\n", s);
+    printf("%s\n", s);
     return;
     //
     //
@@ -21,5 +21,5 @@ ERROR:
     //
     //
     //
-    printf("Error!\n");
+    printf("error!\n");
 }
```

以下のように実装されていてラベルもヒットすると思われる。`private:`, `public:`, `protected:` は除外していると思われる。

http://svn.apache.org/viewvc/subversion/tags/1.9.3/subversion/libsvn_diff/diff_file.c?view=markup#l1483
http://svn.apache.org/viewvc/subversion/tags/1.9.3/subversion/libsvn_diff/diff_file.c?view=markup#l1856

ということで `--diff-cmd` で `/usr/bin/diff` を指定して、そちらの `-F` でラベルがヒットしない正規表現を指定する。

```bash
svn diff --diff-cmd /usr/bin/diff -x "-u -F ^[[:alpha:]\$_][^:/]*\(/\|\$\)"
```

```diff
Index: sample.c
===================================================================
--- sample.c	(リビジョン 3)
+++ sample.c	(作業コピー)
@@ -2,7 +2,7 @@ void func1() {
     //
     //
     //
-    printf("bar\n");
+    printf("BAR\n");
 }
 
 void func2(char *s) {
@@ -12,7 +12,7 @@ void func2(char *s) {
     if (s == NULL) {
         goto ERROR;
     }
-    printf("'%s'\n", s);
+    printf("%s\n", s);
     return;
     //
     //
@@ -21,5 +21,5 @@ void func2(char *s) {
     //
     //
     //
-    printf("Error!\n");
+    printf("error!\n");
 }
```

# Git

以下のように実装されている。

https://github.com/git/git/blob/937978e0f3e750d917768c77665d5f8cfbd802b6/userdiff.c#L127
https://github.com/git/git/blob/21f862b498925194f8f1ebe8203b7a7df756555b/xdiff-interface.c#L251

デフォルトだとラベルが出てしまう。

```diff
diff --git a/sample.c b/sample.c
index 6f04375..95b2e05 100644
--- a/sample.c
+++ b/sample.c
@@ -2,7 +2,7 @@ void func1() {
     //
     //
     //
-    printf("bar\n");
+    printf("BAR\n");
 }
 
 void func2(char *s) {
@@ -12,7 +12,7 @@ void func2(char *s) {
     if (s == NULL) {
         goto ERROR;
     }
-    printf("'%s'\n", s);
+    printf("%s\n", s);
     return;
     //
     //
@@ -21,5 +21,5 @@ ERROR:
     //
     //
     //
-    printf("Error!\n");
+    printf("error!\n");
 }
```

以下を参考に設定を追加して、もう一度試すと関数名が出る。

https://git-scm.com/docs/gitattributes#_defining_a_custom_hunk_header

```text:.git/info/attributes
*.c diff=cpp
```

```diff
diff --git a/sample.c b/sample.c
index 6f04375..95b2e05 100644
--- a/sample.c
+++ b/sample.c
@@ -2,7 +2,7 @@ void func1() {
     //
     //
     //
-    printf("bar\n");
+    printf("BAR\n");
 }
 
 void func2(char *s) {
@@ -12,7 +12,7 @@ void func2(char *s) {
     if (s == NULL) {
         goto ERROR;
     }
-    printf("'%s'\n", s);
+    printf("%s\n", s);
     return;
     //
     //
@@ -21,5 +21,5 @@ void func2(char *s) {
     //
     //
     //
-    printf("Error!\n");
+    printf("error!\n");
 }
```