---
version: '3'

vars:
  EMOJI_END:
    sh: |
      if [ -f '.variables.json' ] && type jq &> /dev/null; then
        BP_END="$(jq -r '.emoji_end' .variables.json)"
        if [ "$BP_END" != 'null' ]; then
          echo "$BP_END"
        else
          if [ "$(jq -r '.emoji_endings[15]' .variables.json)" != 'null' ]; then
            echo "$(jq --arg place "$(shuf -i 0-15 -n 1)" -r '.emoji_endings[($place | tonumber)]' .variables.json)"
          else
            echo ""
          fi
        fi
      fi
  EMOJI_START:
    sh: |
      if [ -f '.variables.json' ] && type jq &> /dev/null; then
        BP_START="$(jq -r '.emoji_start' .variables.json)"
        if [ "$BP_START" != 'null' ]; then
          echo "$BP_START"
        else
          if [ "$(jq -r '.emoji_beginnings[15]' .variables.json)" != 'null' ]; then
            echo "$(jq --arg place "$(shuf -i 0-15 -n 1)" -r '.emoji_beginnings[($place | tonumber)]' .variables.json)"
          else
            echo ""
          fi
        fi
      fi
  GITHUB_ISSUES: true
  GITHUB_WIKI: false
  GITLAB_WIKI: false

env:
  CLICOLOR:
    sh: if [[ "${container:=}" == 'docker' ]]; then echo "0"; else echo "1"; fi

tasks:
  commit:automated:
    deps:
      - remotes
    log:
      start: Running automated commit
    cmds:
      - task --list > /dev/null || (echo "ERROR > Invalid Taskfile(s)!" && exit 1)
      - git add --all
      - cmd: >
          HUSKY=0 git commit -m "☁️ chore(automation): Automated update" -n
        ignore_error: true
    status:
      - '[ "$FULLY_AUTOMATED_TASKS" != "true" ] || [ "$SEMANTIC_RELEASE" == "true" ]'

  convert:folder:submodule:
    deps:
      - :git:github:update
      - :git:gitlab:update
    vars:
      BASENAME:
        sh: basename "$PWD"
      GITLAB_REPO:
        sh: jq -r '.blueprint.repository.gitlab' package.json
    log:
      error: Error converting `{{.BASENAME}}` to a submodule
      start: Converting `{{.BASENAME}}` directory into a submodule
      success: Converted the `{{.BASENAME}}` directory to a submodule
    cmds:
      - git init
      - git remote add origin "{{.GITLAB_REPO}}"
      - git add --all
      - git commit --quiet -m "🧐 refactor(submodule): Adding folder/project to its own git repository."
      - git push --quiet -u --no-progress origin master
      - cd .. && rm -rf {{.BASENAME}}
      - cd .. && git add {{.BASENAME}}
      - cd .. && git commit --quiet -m "🧐 refactor(submodule): Removing folder which will now be a submodule."
      - cd .. && git submodule add -b master "{{.GITLAB_REPO}}" {{.BASENAME}}
      - cd .. && git add {{.BASENAME}}
      - cd .. && git commit --quiet -m "🧐 refactor(submodule): Adding new submodule which was previously a directory."
      - cd .. && git push --quiet -u --no-progress origin HEAD
    preconditions:
      - sh: '[[ ! $(git rev-parse --git-dir) =~ ".git/modules" ]]'
        msg: Cannot convert the directory to a submodule - the directory already appears to be a submodule.

  convert:folder:subrepo:
    deps:
      - :install:software:subrepo
    summary: |
      # Convert Folder to Sub-repo

      This task will work if you have Taskfiles set up in a sub-directory of a project
      that is already a git repository. Instead of using sub-modules, this method makes
      the main repository's structure look as if no sub-module wizardry is going on.

      To use this task, go into a sub-directory that you want to make a git subrepo and
      then run `task git:convert:folder:subrepo` while making sure that the
      `FULLY_AUTOMATED_TASKS` variables is set equal to `true`. There may be other
      tokens required for accessing the APIs of GitHub, GitLab, etc.
    vars:
      BASENAME:
        sh: basename "$PWD"
      GITLAB_REPO:
        sh: jq -r '.blueprint.repository.gitlab' package.json
    log:
      error: Error encountered while converting `{{.BASENAME}}` into a sub-repo
      start: Converting `{{.BASENAME}}` into a sub-repo
      success: Converted `{{.BASENAME}}` into a sub-repo
    cmds:
      - rm -rf .git
      - git config url."git@gitlab.com:".insteadOf "https://gitlab.com/"
      - git config url."git@github.com:".insteadOf "https://github.com/"
      - task: commit:automated
      - |
        ROLE_DIR="$PWD"
        while ! test -d .git; do cd ..; done
        if ! git remote get-url {{.BASENAME}} &> /dev/null; then
          git remote add {{.BASENAME}} {{.GITLAB_REPO}}
        fi
        RELATIVE_DIR="$(echo $ROLE_DIR | sed 's@'"$PWD"'/@@')"
        task git:commit:automated
        HUSKY=0 git subrepo init "$RELATIVE_DIR" -r {{.BASENAME}} -b master
    status:
      - '[ "$FULLY_AUTOMATED_TASKS" != "true" ]'

  filter:
    deps:
      - :install:software:bfg
    desc: Remove large unnecessary and large files from the repository
    summary: |
      # Clean Up Git Repository

      This task will remove files that may have been committed by accident like node_modules.
      It will also use [bfg](https://rtyley.github.io/bfg-repo-cleaner/) to remove all files
      that are over 50MB.
    log:
      error: Error filtering git history
      start: Filtering unnecessary items from git history
      success: Successfully filtered unnecessary items from git history
    cmds:
      - git filter-branch --force --index-filter 'git rm --cached --ignore-unmatch -r **/node_modules/' --prune-empty -- --all
      - bfg --strip-blobs-bigger-than 50M

  push:all:
    deps:
      - :ci:commit:config
      - :git:github:create
      - :git:gitlab:create
    log:
      error: Encountered error while running `git push all master --force || git push origin master`
      start: Running `git push all master --force || git push origin master`
      success: Successfully ran `git push all master --force || git push origin master`
    cmds:
      - |
        if ! git push all master --force; then
          git pull -X theirs origin master
          git add --all
          HUSKY=0 git commit -m "☁️ chore(automation): Automated update to all remotes" -n
          if ! git push all master --force; then
            task git:gitlab:protected:off -- "master"
            git push all master --force
            task git:gitlab:protected:on -- "master"
          fi
        fi
    status:
      - '[ -n "$CI" ] || [ "$SEMANTIC_RELEASE" == "true" ] || [ "$FULLY_AUTOMATED_TASKS" != "true" ]'

  remotes:
    deps:
      - :install:software:git
      - :install:software:jq
      - :install:software:subrepo
    desc: Configure the the `origin`, `gitlab`, `github`, and `all` git remotes
    summary: |
      # Configure Git Remotes

      This task will set the origin to the GitLab repository associated with this project. It will then also create
      a remote named `all` which will point to both the GitLab repository and the GitHub mirror. You can then
      push to both repositories at the same time by running `git push all master`.

      **Example usage:**
      `task git:remotes`
    env:
      GITHUB_REPO:
        sh: jq -r '.blueprint.repository.github' package.json | sed 's/^https:\/\//git@/' | sed 's/github.com\//github.com:/'
      GITLAB_REPO:
        sh: jq -r '.blueprint.repository.gitlab' package.json | sed 's/^https:\/\//git@/' | sed 's/gitlab.com\//gitlab.com:/'
    run: once
    log:
      error: Error setting git remotes
      start: Setting up git remotes
      success: Git remotes are set up
    cmds:
      - git init -q
      - |
        if [ ! -z "$GITLAB_REPO" ]; then
          if git config remote.origin.url > /dev/null; then
            git remote set-url origin "${GITLAB_REPO}.git"
          else
            git remote add origin "${GITLAB_REPO}.git"
            .config/log success 'Added git remote named `origin`'
          fi
          if git config remote.gitlab.url > /dev/null; then
            git remote set-url gitlab "${GITLAB_REPO}.git"
          else
            git remote add gitlab "${GITLAB_REPO}.git"
            .config/log success 'Added git remote named `gitlab`'
          fi
        fi
      - |
        if [ ! -z "$GITHUB_REPO" ]; then
          if git config remote.github.url > /dev/null; then
            git remote set-url github "${GITHUB_REPO}.git"
          else
            git remote add github "${GITHUB_REPO}.git"
            .config/log success 'Added git remote named `github`'
          fi
        fi
      - |
        if [ ! -z "$GITLAB_REPO" ] && [ ! -z "$GITHUB_REPO" ]; then
          if git config remote.all.url > /dev/null; then
            git remote rm all
          fi
          git remote add all "${GITLAB_REPO}.git"
          git remote set-url --add --push all "${GITHUB_REPO}.git"
          git remote set-url --add --push all "${GITLAB_REPO}.git"
          .config/log success 'Added git remote named `all`'
        fi
    status:
      - '[[ "$(git config remote.all.url)" == "${GITLAB_REPO}.git" ]] || [ -n "$CI" ]'
      - '[[ "$(git config remote.github.url)" == "${GITHUB_REPO}.git" ]] || [ -n "$CI" ]'
      - '[[ "$(git config remote.gitlab.url)" == "${GITLAB_REPO}.git" ]] || [ -n "$CI" ]'

  remove:history:cli:
    deps:
      - :install:software:git
    log:
      error: Failed to remove `{{.CLI_ARGS}}` from the git history
      start: Removing `{{.CLI_ARGS}}` from the git history
      success: Removed `{{.CLI_ARGS}}` from the git history
    cmds:
      - git filter-branch --index-filter 'git rm -rf --cached --ignore-unmatch {{.CLI_ARGS}}' HEAD

  remove:submodules:
    deps:
      - :install:software:git
    desc: Remove all submodules in the current directory and optionally filter by RegEx
    summary: |
      # Remove submodules in current directory

      This task will remove all the submodules in the current directory and its' children.
      You can optionally specify RegEx to only remove submodules that match a particular pattern.
      Please note that this task is not _perfect_. You should commit your current changes before using it
      and then reset the repository with `git reset --hard HEAD` if anything pops up on `git status` that
      you do not like after running it.

      **Example removing all submodules that are children of the working directory:**
      `task git:remove-submodules`

      **Example removing all submodules that are children of the working directory and matching a pattern:**
      `task git:remove-submodules -- docs`
    vars:
      GITMODULES_PATH: .gitmodules
      REGEX_ARG:
        sh: if [ -z "{{.CLI_ARGS}}" ]; then echo ""; else echo " | grep {{.CLI_ARGS}}"; fi
      RELATIVE_PATH:
        sh: pwd | sed "s,^$(git rev-parse --show-toplevel),," | cut -c2-
      # /home/hawkwood/Downloads/Backup/Code
      ROOT_GIT:
        sh: git rev-parse --git-dir | sed 's/\.git\/modules\(.*\)/.gitmodules/' | sed 's/\.git$/.gitmodules/' | sed 's/.gitmodules$//'
      # /home/hawkwood/Downloads/Backup/Code/docker/ci-pipeline/hadolint
      TOP_LEVEL:
        sh: git rev-parse --show-toplevel
    log:
      error: Error encountered while attempting to remove submodules
      start: Attempting to remove submodules
      success: Successfully removed submodules
    cmds:
      - |
        if [ -f '.gitmodules' ]; then
          MODULE_PATHS=$(git config --file "{{.GITMODULES_PATH}}" --name-only --get-regexp "{{.RELATIVE_PATH}}" |
            sed 's/^submodule\.//' | grep "path$" | sed 's/\.path$//'{{.REGEX_ARG}})
          for MODULE_PATH in "$MODULE_PATHS"; do
            # https://github.com/a14m/gitsubmodule/blob/master/gitsubmodule
            git config -f '{{.GITMODULES_PATH}}' --remove-section "submodule.$MODULE_PATH" | true
            git add '{{.GITMODULES_PATH}}'
            # /home/hawkwood/Downloads/Backup/Code/.git/modules/docker/ci-pipeline/hadolint/config
            {{if .ROOT_GIT}}
              CONFIG_PATH="$(pwd | sed 's,{{.ROOT_GIT}},,')"
            {{else}}
              CONFIG_PATH='.git'
            {{end}}
            git config -f '{{.ROOT_GIT}}./{{if ne .ROOT_GIT ""}}.git/modules/{{end}}'"$CONFIG_PATH"'/config' --remove-section "submodule.$MODULE_PATH"
            git rm --cached "$MODULE_PATH"
            rm -rf "{{.ROOT_GIT}}./.git/modules/$CONFIG_PATH"
            rm -rf "$MODULE_PATH"
          done
          .config/log success "Successfully removed the project's submodules"
        else
          .config/log info 'This task does not run unless there is a `.gitmodules` file in the current directory'
        fi

  update:
    cmds:
      - task: update:start
    status:
      - '[ "$FULLY_AUTOMATED_TASKS" != "true" ]'

  update:finish:
    deps:
      - :git:gitlab:update
      - :git:github:update
    run: once

  update:start:
    run: once
    cmds:
      - task: :git:gitlab:create
      - task: :git:github:create
      - task: update:finish
    status:
      - '[ -n "$CI" ] || ([ -z "$GITLAB_TOKEN" ] && [ -z "$GITHUB_TOKEN" ])'
