File: integration_tests_sync.sh

package info (click to toggle)
sqlglot 30.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 15,644 kB
  • sloc: python: 96,110; sql: 23,456; makefile: 75
file content (167 lines) | stat: -rwxr-xr-x 5,582 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
#!/usr/bin/env bash
set -euo pipefail

# Unset git env vars that leak from parent hook context into submodule commands
unset GIT_INDEX_FILE GIT_DIR

SUBMODULE_DIR="sqlglot-integration-tests"

# Graceful no-op when the submodule is absent (public contributors)
[ -e "$SUBMODULE_DIR/.git" ] || exit 0

# Ensure the submodule is on a branch matching the parent's branch name.
# Creates the branch if it doesn't exist.
ensure_branch() {
  local branch
  branch=$(git rev-parse --abbrev-ref HEAD)
  [ "$branch" = "HEAD" ] && return 0

  local current
  current=$(git -C "$SUBMODULE_DIR" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "")

  if [ "$current" != "$branch" ]; then
    # Stash any uncommitted/untracked changes so branch switch doesn't fail
    local stashed=0
    if [ -n "$(git -C "$SUBMODULE_DIR" status --porcelain)" ]; then
      git -C "$SUBMODULE_DIR" stash push --include-untracked --quiet 2>/dev/null && stashed=1
    fi

    if git -C "$SUBMODULE_DIR" show-ref --verify --quiet "refs/heads/$branch"; then
      git -C "$SUBMODULE_DIR" checkout "$branch" --quiet
    else
      git -C "$SUBMODULE_DIR" checkout -b "$branch" --quiet
    fi

    # Restore stashed changes on the new branch
    if [ "$stashed" = "1" ]; then
      git -C "$SUBMODULE_DIR" stash pop --quiet 2>/dev/null || true
    fi
  fi
}

case "${1:-}" in
  checkout)
    # No-op: branch creation is deferred to commit/post-commit to avoid
    # creating empty branches when switching parent branches.
    ;;

  commit)
    # Skip if submodule has no changes
    [ -n "$(git -C "$SUBMODULE_DIR" status --porcelain)" ] || exit 0

    # Only auto-commit submodule changes when the submodule pointer is already
    # staged in the parent (i.e. the user explicitly `git add`-ed it). This
    # prevents surprise commits of unrelated WIP in the submodule working tree.
    git diff --cached --quiet -- "$SUBMODULE_DIR" && exit 0

    ensure_branch

    if [ -n "$(git -C "$SUBMODULE_DIR" status --porcelain)" ]; then
      BRANCH=$(git rev-parse --abbrev-ref HEAD)
      git -C "$SUBMODULE_DIR" add -A
      git -C "$SUBMODULE_DIR" commit -m "Sync: $BRANCH"
    fi

    # Stage the updated submodule pointer in the parent
    if ! git diff --quiet -- "$SUBMODULE_DIR"; then
      git add "$SUBMODULE_DIR"
    fi
    ;;

  post-commit)
    # The pre-commit framework's stashing undoes submodule changes made during
    # pre-commit. Re-commit the submodule and amend the parent to include it.

    # Only act if the most recent parent commit references the submodule. This
    # prevents the post-commit hook from auto-committing unrelated submodule WIP
    # (e.g. when switching branches or pulling on main).
    if ! git diff-tree --no-commit-id --name-only -r HEAD | grep -q "^${SUBMODULE_DIR}$"; then
      exit 0
    fi

    # Skip if submodule has no changes and pointer is up to date
    if [ -z "$(git -C "$SUBMODULE_DIR" status --porcelain)" ] && git diff --quiet -- "$SUBMODULE_DIR"; then
      exit 0
    fi

    ensure_branch

    if [ -n "$(git -C "$SUBMODULE_DIR" status --porcelain)" ]; then
      BRANCH=$(git rev-parse --abbrev-ref HEAD)
      git -C "$SUBMODULE_DIR" add -A
      git -C "$SUBMODULE_DIR" commit -m "Sync: $BRANCH"
    fi

    if ! git diff --quiet -- "$SUBMODULE_DIR"; then
      git add "$SUBMODULE_DIR"
      git commit --amend --no-edit --no-verify
    fi
    ;;

  push)
    BRANCH=$(git rev-parse --abbrev-ref HEAD)
    case "$BRANCH" in main|master) exit 0 ;; esac

    ensure_branch

    cd "$SUBMODULE_DIR"

    # Check if there are local commits to push
    if git rev-parse --verify "@{upstream}" >/dev/null 2>&1; then
      UNPUSHED=$(git rev-list --count "@{upstream}..HEAD")
    else
      UNPUSHED=$(git rev-list --count "origin/main..HEAD" 2>/dev/null || echo "0")
    fi
    [ "$UNPUSHED" = "0" ] && exit 0

    # Push the branch, rebasing first if needed
    git push -u origin "$BRANCH" 2>/dev/null || {
      git pull --rebase --autostash || {
        git rebase --abort 2>/dev/null || true
        echo "ERROR: Conflicts pushing integration tests. Resolve with:" >&2
        echo "  cd $SUBMODULE_DIR && git pull --rebase" >&2
        exit 1
      }
      git push -u origin "$BRANCH"
    }

    # Create a PR if one doesn't exist (requires gh CLI)
    if command -v gh >/dev/null 2>&1; then
      EXISTING=$(gh pr list --head "$BRANCH" --json number --jq 'length' 2>/dev/null || echo "0")
      if [ "$EXISTING" = "0" ]; then
        PARENT_URL=$(git -C .. remote get-url origin 2>/dev/null | sed 's/\.git$//' | sed 's|git@github.com:|https://github.com/|')
        BODY="Parent branch: ${PARENT_URL}/tree/${BRANCH}"
        gh pr create \
          --title "$BRANCH" \
          --body "$BODY" \
          --head "$BRANCH" 2>/dev/null || true
      fi
    fi
    ;;

  merge)
    # Sync submodule to the parent's pointer
    git submodule update --init 2>/dev/null || true
    ensure_branch

    cd "$SUBMODULE_DIR"
    BRANCH=$(git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "HEAD")
    [ "$BRANCH" = "HEAD" ] && exit 0

    git fetch origin --quiet 2>/dev/null || exit 0

    BEHIND=$(git rev-list --count "HEAD..origin/$BRANCH" 2>/dev/null || echo "0")
    [ "$BEHIND" = "0" ] && exit 0

    if ! git pull --rebase --autostash --quiet 2>/dev/null; then
      git rebase --abort 2>/dev/null || true
      echo "WARNING: Rebase conflicts in $SUBMODULE_DIR." >&2
      echo "Resolve with: cd $SUBMODULE_DIR && git pull --rebase" >&2
    fi
    ;;

  *)
    echo "Usage: $0 {checkout|commit|post-commit|push|merge}" >&2
    exit 1
    ;;
esac