name: Formatting your code
on:
  # We are interested only in master and PRs, but GitHub explicitly forbids
  # pushing to the fork when an event is triggered on the base repo.
  # We therefore need to intercept all calls and filter out the ones we are
  # interested in.
  # For master, and branches with an open PR, we run utils/fix_formatting.py.
  # We then commit and push the changes to the branch.
  # If someone pushes to the branch while we're still formatting,
  # we exit 1 instead of pushing.
  # For other branches without an open PR, we also run fix_formatting.py, but
  # we do not push anything, only signal the code quality by exiting 0 or 1.
  push:
jobs:
  run_formatting:
    name: Run fix_formatting.py
    runs-on: ubuntu-20.04
    steps:
    - name: Checkout
      uses: actions/checkout@v2
      with:
        persist-credentials: false
    - name: Fetching branch info
      run: |
        echo "branch=${GITHUB_REF##*/}" >> $GITHUB_ENV
        git config --global user.name "The Widelands Code Formatting Bot"
        export ACTOR_NAME="${GITHUB_REPOSITORY%/*}"
        if [ "$ACTOR_NAME" == "widelands" ]
        then
          export ACTOR_NAME="bunnybot"
          git config --global user.email "bunnybot@widelands.org"
        else
          git config --global user.email "$(git log -1 --format=\"%ae\")"
        fi
        export PAT="${{ secrets.WIDELANDS_FORMAT_TOKEN }}"
        if [ -z "$PAT" ]
        then
          export PAT="${{ secrets.GITHUB_TOKEN }}"
          echo "WARNING: You did not create a personal access token yet. Please do so soon! See https://github.com/widelands/widelands/#code for more information."
        fi
        echo "PAT=$PAT" >> $GITHUB_ENV
        echo "ACTOR_NAME=$ACTOR_NAME" >> $GITHUB_ENV
        # copied from https://github.com/stefanzweifel/git-auto-commit-action/blob/master/entrypoint.sh
        cat <<- EOF > $HOME/.netrc
        machine github.com
        login $ACTOR_NAME
        password $PAT
        machine api.github.com
        login $ACTOR_NAME
        password $PAT
        EOF
        chmod 600 $HOME/.netrc
    - name: Installing python
      uses: actions/setup-python@v1
      with:
        python-version: 3.x
    - name: Installing formatting tools
      run: |
        sudo apt-get update
        sudo apt-get purge -y clang-11 clang-format-11
        sudo apt-get install clang-format-10
        pip install pyformat
        # Use clang-format 10 as default until we choose to migrate to 11
        sudo update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-10 100
        sudo update-alternatives --install /usr/bin/clang clang /usr/bin/clang-10 100
        sudo update-alternatives --install /usr/bin/clang-format clang-format /usr/bin/clang-format-10 100
        # Quit on wrong version
        clang-format --version | grep 10.0.0
    - name: Invoking fix_formatting.py
      run: python3 ./utils/fix_formatting.py
    - name: Gathering changes
      run: |
        nrfiles=$(git status -s | wc -l)
        if [ $nrfiles == 0 ]
        then
          echo "Nothing to do"
          files=""
        else
          if [ $nrfiles == 1 ]
          then
            echo "1 file formatted"
            files=$(git status -s)
            files="'${files#???}' was automatically formatted."
          else
            echo "$nrfiles files formatted"
            files="$nrfiles files were automatically formatted."
          fi
          if [ "$branch" == "master" ]
          then
            echo "Always push master branch ($GITHUB_REF)"
          else
            forkname=${{ github.repository }}
            # grep returns 1 if the branch is not found
            set +e
            output=$(curl -i "https://api.github.com/repos/widelands/widelands/pulls?state=open&head=${forkname%%/*}:$branch" | grep "$branch")
            set -e
            if [ -z "$output" ]
            then
              echo "Branch $branch in repository $forkname does not have an open pull request, so no changes will be pushed. Please note however that your code is not properly formatted:"
              git status -s
              git --no-pager diff --cached
              exit 1
            else
              echo "Branch $branch in repository $forkname has an open pull request. Changes will be pushed."
            fi
          fi
        fi
        echo "COMMIT_MESSAGE=$files" >> $GITHUB_ENV
    - name: Pushing changes
      run: |
        if [ -z "$COMMIT_MESSAGE" ]
        # skip if there's nothing to do
        then
          echo "Code was already correctly formatted"
          exit 0
        fi
        # curl exits 23 because grep will kill it after the first match
        set +e
        latest=$(curl -i "https://api.github.com/repos/${{ github.repository }}/commits/$branch" | grep -m 1 "\"sha\": ")
        set -e
        latest=${latest#*: \"}
        latest=${latest%\",}
        if [ "$latest" == "${{ github.sha }}" ]
        then
          echo "No remote changes"
          git remote add push_target https://${ACTOR_NAME}:${PAT}@github.com/${GITHUB_REPOSITORY}.git
          git commit -m "$COMMIT_MESSAGE"
          git push push_target "$branch"
          echo "Changes were successfully pushed to $branch at ${{ github.repository }}. Don't forget to run 'git pull' before pushing to the branch again."
        else
          echo "The remote branch '$branch' ($GITHUB_REF) from '${{ github.repository }}' was updated from '${{ github.sha }}' to '$latest', cancel"
          exit 1
        fi
