0

I'm trying to edit all commit messages of a range based on the following criteria:

  • If the message contains "Jobs:". Leave the message as is.
  • If the message does NOT contain it, add it to the end, with an extra line based on the commit author.

In other words, I want all commits to have a suffix like this:

Jobs:
<author_job>

I came up with something like this:

#!/bin/bash

if [ "$#" -lt "2" ]; then
    echo Syntax: $0 \<initial commit\> \<final commit\>
    exit
fi

INITIAL_COMMIT=$1
FINAL_COMMIT=$2

FILTER="
    ORIGINAL_COMMIT=\`cat\` &&
    echo \${ORIGINAL_COMMIT} &&
    if [ \"\${ORIGINAL_COMMIT/\"Jobs:\"}\" == \"\${ORIGINAL_COMMIT}\" ]; then
        echo
        echo Jobs:
        case "\${GIT_AUTHOR_EMAIL}" in
            \"user1@company.com\") echo \"JOB_ID_USER_1\" ;;
            \"user2@company.com\") echo \"JOB_ID_USER_2\" ;;
            \"user3@company.com\") echo \"JOB_ID_USER_3\" ;;
            *)                     echo UNKNOWN ;;
        esac
    fi
"

echo Running git filter branch
git filter-branch --msg-filter "${FILTER}" ${INITIAL_COMMIT}..${FINAL_COMMIT}

However I'm having trouble detecting if the commit message already has the suffix or not. Without the if condition, it works really well, but it will add the suffix to messages that already have it.

This is the filter in this case:

FILTER="
    cat &&
    echo &&
    echo Jobs: &&
    case "\${GIT_AUTHOR_EMAIL}" in
        \"user1@company.com\") echo \"JOB_ID_USER_1\" ;;
        \"user2@company.com\") echo \"JOB_ID_USER_2\" ;;
        \"user3@company.com\") echo \"JOB_ID_USER_3\" ;;
        *)                              echo UNKNOWN ;;
    esac
"

Does anyone have idea how to get around it?

I've seen some people doing python scripts to solve similar problems. Is it a good idea?

Thanks.

Marcus
  • 1,675
  • 3
  • 18
  • 29

2 Answers2

1

Use [[ \${ORIGINAL_COMMIT} != *\"Jobs:\"* ]] for your test, or any of the other comparisons in String contains in bash.

The echo \${ORIGINAL_COMMIT} line is also removing newlines in the commit message. You'll want to quote that: echo \"\${ORIGINAL_COMMIT}\"

Overall, the filter now looks like:

FILTER="
    ORIGINAL_COMMIT=\`cat\` &&
    echo \"\${ORIGINAL_COMMIT}\" &&
    case \"\${ORIGINAL_COMMIT}\" in
      *Jobs:*) ;; # Already present, do nothing
      *)          # Otherwise, add
        echo
        echo Jobs:
        case "\${GIT_AUTHOR_EMAIL}" in
            \"user1@company.com\") echo \"JOB_ID_USER_1\" ;;
            \"user2@company.com\") echo \"JOB_ID_USER_2\" ;;
            \"user3@company.com\") echo \"JOB_ID_USER_3\" ;;
            *)                     echo UNKNOWN ;;
        esac
        ;;
    esac
"
Kristján
  • 18,165
  • 5
  • 50
  • 62
  • I tried using the string contains like this. It doesn't work: (1/197)/usr/lib/git-core/git-filter-branch: 4: eval: [[: not found. I'm also not sure it is possible to use the `cat` to put the original message in a variable. – Marcus Jul 24 '15 at 16:31
  • Actualy, the cat trick works. But the string comparisson doesn't. – Marcus Jul 24 '15 at 16:35
  • Try more of the answers in that other question. [This one](http://stackoverflow.com/a/229585/802618) purports to be portable. – Kristján Jul 24 '15 at 16:58
  • 1
    The case solution works fine! Great suggestion. Thanks very much. – Marcus Jul 24 '15 at 17:51
  • Updated the example with a more portable version, though I couldn't figure out a way to negate the substring match and get down to one case. Have you? – Kristján Jul 24 '15 at 23:04
  • No, I could not find it. I believe the case hack really must be like this. – Marcus Jul 27 '15 at 13:22
0

As proposed by @Kristján, it is possible to use case to search for substrings.

FILTER="
    ORIGINAL_COMMIT=\`cat\` &&
    case "\${GIT_AUTHOR_EMAIL}" in
        \"user1@company.com\") JOB_ID=\"JOB_ID_USER_1\" ;;
        \"user2@company.com\") JOB_ID=\"JOB_ID_USER_2\" ;;
        \"user3@company.com\") JOB_ID=\"JOB_ID_USER_3\" ;;
        *)                     JOB_ID=\"UNKNOWN\" ;;
    esac &&
    case \"\${ORIGINAL_COMMIT}\" in
        *Jobs:*) ;;
        *)
            echo
            echo Jobs:
            echo \"\t\${JOB_ID}\"
    esac
"

It is also possible to use python to work around this. A bit more troublesome than the solution above, but it also gives you more power since you are using python.

PWD=`pwd`

FILTER="
    ORIGINAL_COMMIT=\`cat\` &&
    case "\${GIT_AUTHOR_EMAIL}" in
        \"user1@company.com\") JOB_ID=\"JOB_ID_USER_1\" ;;
        \"user2@company.com\") JOB_ID=\"JOB_ID_USER_2\" ;;
        \"user3@company.com\") JOB_ID=\"JOB_ID_USER_3\" ;;
        *)                     JOB_ID=\"UNKNOWN\" ;;
    esac
    echo \"\${ORIGINAL_COMMIT}\" | ${PWD}/Process_Commit.py \${JOB_ID}
"

The python script (Process_Commit.py):

#!/usr/bin/python
import sys

job_id = sys.argv[1]

adjust = True
for line in sys.stdin:
    sys.stdout.write(line)
    if line.find("Jobs:") != -1:
        adjust = False

if adjust == True:
    print
    print "Jobs:"
    print "\t",job_id
Marcus
  • 1,675
  • 3
  • 18
  • 29