#!/bin/bash
#
# Copyright (C) 2020-2026 Red Hat, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

set -e
set -x
GIT_CLONE_OPTIONS="--filter=tree:0"

TOPDIR=$(cd $(dirname $0); pwd)

if [[ $0 =~ .*-podman$ ]]; then
    SUFFIX=-podman
else
    SUFFIX=
fi

if [ -r "$TOPDIR/common$SUFFIX" ]; then
    BASEDIR="$TOPDIR"
else
    BASEDIR=/usr/share/dci-pipeline
fi

source "$BASEDIR/common$SUFFIX"

GH_API_URL=${REV_PROXY_URL:-https://api.github.com}
GH_CLONE_URL=${REV_PROXY_URL:-https://github.com}
# remove https:// or http:// from GH_CLONE_URL for use in git clone URL
GH_CLONE_BASE_URL=${GH_CLONE_URL#https://}
GH_CLONE_BASE_URL=${GH_CLONE_BASE_URL#http://}

export GIT_COMMITTER_NAME="Extractor"
export GIT_COMMITTER_EMAIL="noaddress@nowhere.com"

TARGET="$1"
test -n "$TARGET" -a -d "$TARGET"

# git log -1 | while read line; do
while read line; do
  if ! grep -Eiq '^\s*(build-depends|depends-on):' <<< $line; then
      continue
  fi
  echo "Processing line '$line'"
  cd "${TARGET}"
  # try to find a github pr first
  if grep -Eiq 'https://github.com/.*/pull' <<< $line; then
      pr=$(sed -e 's@.*/pull/'@@ <<< $line)
      proj=$(sed -e 's@\(build-Depends\|depends-on\):\s*https://github.com/\(.*\)/pull/.*@\2@i' <<< $line)
      dir=$(basename $proj)

      if [ -n "$pr" -a -n "$proj" ]; then
          echo "Extracting PR $pr from $proj"

          GITHUB_REPO_TOKEN=$($BASEDIR/get-config-entry "https://github.com/$proj" github_token "$GITHUB_TOKEN")
          GITHUB_REPO_LOGIN=$($BASEDIR/get-config-entry "https://github.com/$proj" github_login "$GITHUB_LOGIN")
          GITHUB_REPO_SSH_ID=$($BASEDIR/get-config-entry "https://github.com/$proj" github_ssh_id "$GITHUB_SSH_ID")
          GIT_REPO_CLONE_OPTIONS=$($BASEDIR/get-config-entry "https://github.com/$proj" git_clone_options "$GIT_CLONE_OPTIONS")
          if [ -n "$GITHUB_REPO_TOKEN" ]; then
              curl -s -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $GITHUB_REPO_TOKEN" $GH_API_URL/repos/$proj/pulls/$pr > $dir-$pr.json
          else
              curl -s -H "Accept: application/vnd.github.v3+json" $GH_API_URL/repos/$proj/pulls/$pr > $dir-$pr.json
          fi

          if [ ! -d $dir ]; then
              if [ -n "$GITHUB_REPO_SSH_ID" ]; then
                  ssh-agent bash -c "ssh-add $HOME/.ssh/$GITHUB_REPO_SSH_ID; git clone ${GIT_REPO_CLONE_OPTIONS} git@github.com:$proj $dir"
              elif [ -n "$GITHUB_LOGIN" ] && [ -n "$GITHUB_REPO_TOKEN" ]; then
                  git clone ${GIT_REPO_CLONE_OPTIONS} "https://$GITHUB_REPO_LOGIN:$GITHUB_REPO_TOKEN@$GH_CLONE_BASE_URL/$proj" "$dir"
              else
                  git clone ${GIT_REPO_CLONE_OPTIONS} "$GH_CLONE_URL/$proj" "$dir"
              fi
          fi

          BRANCH=$(jq -r .base.ref "$dir-$pr.json")
          cd $dir
          git stash || :
          git checkout "$BRANCH"
          # remove old branch if it exists
          git branch -D pr$pr || :
          if [ -n "$GITHUB_REPO_SSH_ID" ]; then
              ssh-agent bash -c "ssh-add $HOME/.ssh/$GITHUB_REPO_SSH_ID; git fetch origin pull/$pr/head:pr$pr"
          else
              git fetch origin "pull/$pr/head:pr$pr"
          fi
          # check if branch is already merged
          if [ "$(jq -r .merged ../$dir-$pr.json)" = true ]; then
              git checkout "$BRANCH"
          else
              git checkout pr$pr
              git rev-parse HEAD > .original-commit-id
              if [ -n "$GITHUB_REPO_SSH_ID" ]; then
                  ssh-agent bash -c "ssh-add $HOME/.ssh/$GITHUB_REPO_SSH_ID; git fetch origin $BRANCH"
              else
                  git fetch origin "$BRANCH"
              fi
              if ! git rebase "origin/$BRANCH"; then
                  git rebase --abort
                  # set username and email for git merge to work
                  git config user.name "extract-dependencies"
                  git config user.email "extract-dependencies@dci.com"
                  if ! git merge "origin/$BRANCH"; then
                      # unset username and email
                      git config --unset user.name
                      git config --unset user.email
                      $BASEDIR/send_status "$TARGET" error "ERROR unable to rebase PR $pr from $proj branch $BRANCH"
                      rm -rf $TARGET
                      exit 1
                  fi
                  # unset username and email
                  git config --unset user.name
                  git config --unset user.email
              fi
          fi
      fi
  else
      # try to find a gerrit review
      changeid=$(sed -e 's@\s*\(build-depends\|depends-on\):\s*\(https://softwarefactory-project.io/.*/\)\{0,1\}\(.*\)\s*@\3@i' <<< $line)
      if [ -n "$changeid" ]; then
          curl -s https://softwarefactory-project.io/r/changes/${changeid}?o=CURRENT_REVISION | tail -n +2 > ${changeid}.json
          PROJECT=$(jq -r .project ${changeid}.json)
          CURREV=$(jq -r .current_revision ${changeid}.json)
          REPOURL=$(jq -r ".revisions[\"$CURREV\"].fetch[\"anonymous http\"].url" ${changeid}.json)
          REVID=$(jq -r ".revisions[\"$CURREV\"].fetch[\"anonymous http\"].ref" ${changeid}.json)

          if [ ! -d $PROJECT ]; then
              git clone ${GIT_CLONE_OPTIONS} $REPOURL $PROJECT
          fi

          cd $PROJECT
          git stash || :
          git checkout master
          # remove old branch if it exists
          git branch -D gr$changeid || :
          git fetch $REPOURL $REVID:gr$changeid
          # check if branch is already merged
          if [ "$(jq -r .status ../${changeid}.json)" = "MERGED" ]; then
              git checkout master
          else
              git checkout gr$changeid
              git rev-parse HEAD > .original-commit-id
              git fetch origin master
              if ! git rebase origin/master; then
                  $BASEDIR/send_status $TARGET error "ERROR unable to rebase Gerrit review $changeid from $PROJECT"
                  rm -rf $TARGET
                  exit 1
              fi
          fi
      fi
  fi
done
