diff --git a/.github/workflows/pre-commit.yml b/.github/workflows/pre-commit.yml index d64ed8e6..330ed25c 100644 --- a/.github/workflows/pre-commit.yml +++ b/.github/workflows/pre-commit.yml @@ -8,6 +8,9 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - - uses: actions/setup-python@v3 - - uses: pre-commit/action@v3.0.1 + - uses: actions/checkout@v4 + with: + # For PRs from forks, checkout the merge commit to avoid branch name conflicts + ref: ${{ github.event.pull_request.head.sha || github.sha }} + - uses: actions/setup-python@v3 + - uses: pre-commit/action@v3.0.1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 834766d2..fc2fa05c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -2,9 +2,9 @@ name: Test on: push: - branches: [ '*' ] + branches: ["*"] pull_request: - branches: [ '*' ] + branches: ["*"] jobs: test: @@ -14,16 +14,31 @@ jobs: os: [ubuntu-latest, macos-latest] steps: - - uses: actions/checkout@v2 - - if: startsWith(matrix.os, 'macos') - run: brew install bash - - run: - git config --global user.email "you@example.com"; - git config --global user.name "Your Name"; - git config --global init.defaultBranch "master"; - git config --global --add safe.directory "$PWD"; - git config --global --add safe.directory "$PWD.git"; - - if: startsWith(matrix.os, 'macos') - run: make test - - if: startsWith(matrix.os, 'ubuntu') - run: make docker-tests + - uses: actions/checkout@v4 + with: + repository: ${{ github.event.pull_request.head.repo.full_name || github.repository }} + ref: ${{ github.event.pull_request.head.ref || github.ref_name }} + token: ${{ secrets.GITHUB_TOKEN }} + - name: Ensure we're on a proper branch + run: | + if [ "${{ github.event_name }}" = "pull_request" ]; then + # For PRs, create a local branch from the HEAD + git checkout -b "pr-${{ github.event.pull_request.number }}-${{ github.event.pull_request.head.ref }}" + elif git symbolic-ref -q HEAD >/dev/null; then + # Already on a branch, nothing to do + echo "Already on branch $(git branch --show-current)" + else + # Detached HEAD, create a branch + git checkout -b "workflow-$(date +%s)" + fi + - if: startsWith(matrix.os, 'macos') + run: brew install bash + - run: git config --global user.email "you@example.com"; + git config --global user.name "Your Name"; + git config --global init.defaultBranch "master"; + git config --global --add safe.directory "$PWD"; + git config --global --add safe.directory "$PWD.git"; + - if: startsWith(matrix.os, 'macos') + run: make test + - if: startsWith(matrix.os, 'ubuntu') + run: make docker-tests diff --git a/Makefile b/Makefile index 3e9276be..dffa0a23 100644 --- a/Makefile +++ b/Makefile @@ -22,16 +22,20 @@ INSTALL_EXT ?= $(INSTALL_LIB)/$(NAME).d INSTALL_MAN1 ?= $(DESTDIR)$(PREFIX)/share/man/man1 # Docker variables: -DOCKER_TAG ?= 0.0.7 -DOCKER_IMAGE := ingy/bash-testing:$(DOCKER_TAG) -BASH_VERSIONS ?= 5.2 5.1 5.0 4.4 4.3 4.2 4.1 4.0 -DOCKER_TESTS := $(BASH_VERSIONS:%=docker-test-%) -GIT_VERSIONS := 2.48 2.40 2.30 2.29 2.25 2.17 2.7 +DOCKER_TAG ?= admorgan/git-subrepo-testing:1.0 +DOCKER_IMAGE := $(DOCKER_TAG) +BASH_VERSIONS ?= 5.3 5.2 5.1 5.0 4.4 4.3 4.2 4.1 4.0 +GIT_VERSIONS := 2.51 2.48 2.40 2.30 2.29 2.25 2.23 + +# Create matrix of all bash/git combinations for comprehensive testing +BASH_GIT_COMBINATIONS := $(foreach bash,$(BASH_VERSIONS),$(foreach git,$(GIT_VERSIONS),$(bash)-$(git))) +DOCKER_TESTS := $(BASH_GIT_COMBINATIONS:%=docker-test-%) +DOCKER_BASH_TESTS := $(BASH_VERSIONS:%=docker-bash-test-%) prove ?= test ?= test/ -bash ?= 5.2 -git ?= 2.48 +bash ?= 5.3 +git ?= 2.51 # Basic targets: default: help @@ -43,6 +47,16 @@ help: @echo 'install Install $(NAME)' @echo 'uninstall Uninstall $(NAME)' @echo 'env Show environment variables to set' + @echo '' + @echo 'Docker testing:' + @echo 'docker-build Build Docker image with multiple bash/git versions' + @echo 'docker-tests Test ALL bash/git combinations (comprehensive)' + @echo 'docker-bash-tests Test all bash versions with default git (faster)' + @echo 'docker-test Test specific bash/git: make docker-test bash=5.1 git=2.25' + @echo '' + @echo 'Available bash versions: $(BASH_VERSIONS)' + @echo 'Available git versions: $(GIT_VERSIONS)' + @echo '' .PHONY: test test: @@ -53,10 +67,26 @@ test-all: test docker-tests docker-test: $(call docker-make-test,$(bash),$(git)) +docker-build: + docker build -t $(DOCKER_TAG) test/ + +# Test all bash/git combinations (comprehensive but slow) docker-tests: $(DOCKER_TESTS) +# Test all bash versions with default git (faster option) +docker-bash-tests: $(DOCKER_BASH_TESTS) + + + +# Parse bash-git combination from target name $(DOCKER_TESTS): - $(call docker-make-test,$(@:docker-test-%=%),$(git)) + $(eval BASH_VER := $(shell echo "$(@:docker-test-%=%)" | cut -d'-' -f1)) + $(eval GIT_VER := $(shell echo "$(@:docker-test-%=%)" | cut -d'-' -f2)) + $(call docker-make-test,$(BASH_VER),$(GIT_VER)) + +# Test specific bash version with default git +$(DOCKER_BASH_TESTS): + $(call docker-make-test,$(@:docker-bash-test-%=%),$(git)) # Install support: install: @@ -109,6 +139,7 @@ clean: define docker-make-test docker run --rm \ + --user $(shell id -u):$(shell id -g) \ -v $(PWD):/git-subrepo \ -w /git-subrepo \ $(DOCKER_IMAGE) \ diff --git a/Meta b/Meta index 17e8e93f..8f5f2845 100644 --- a/Meta +++ b/Meta @@ -17,7 +17,7 @@ author: requires: bash: 4.0.0 - git: 2.7.0 + git: 2.23.0 test: cmd: make test install: make install diff --git a/ReadMe.pod b/ReadMe.pod index 6f224bb0..7f2e00c6 100644 --- a/ReadMe.pod +++ b/ReadMe.pod @@ -114,7 +114,7 @@ The best short answer is: The complete "Installation Instructions" can be found below. -Note: git-subrepo needs a git version (> 2.7) that supports worktree:s. +Note: git-subrepo needs a git version >= 2.23) due to changes in --is-ansestor. =head1 Commands diff --git a/lib/git-subrepo b/lib/git-subrepo index 954380b8..dfd12017 100755 --- a/lib/git-subrepo +++ b/lib/git-subrepo @@ -32,7 +32,7 @@ bash+:import :std can version-check VERSION=0.4.9 REQUIRED_BASH_VERSION=4.0 -REQUIRED_GIT_VERSION=2.7.0 +REQUIRED_GIT_VERSION=2.23.0 GIT_TMP=$(git rev-parse --git-common-dir 2> /dev/null || echo .git)/tmp # `git rev-parse` turns this into a getopt parser and a command usage message: @@ -212,7 +212,18 @@ command:clone() { command:init() { command-setup +subdir local default_branch= - default_branch=$(git config --get --default=master init.defaultbranch) + # Check if Git supports init.defaultbranch (Git 2.28+) + local git_version + local git_major + local git_minor + git_version=$(git --version | sed 's/git version //' | sed 's/\..*//') + git_major=$(echo "$git_version" | cut -d. -f1) + git_minor=$(echo "$git_version" | cut -d. -f2) + if [[ $git_major -gt 2 ]] || [[ $git_major -eq 2 && $git_minor -ge 28 ]]; then + default_branch=$(git config --get init.defaultbranch 2>/dev/null || echo "master") + else + default_branch="master" + fi local remote=${subrepo_remote:=none} local branch=${subrepo_branch:=$default_branch} diff --git a/test/Dockerfile b/test/Dockerfile index 8f0fd89e..6a0a00c2 100644 --- a/test/Dockerfile +++ b/test/Dockerfile @@ -1,112 +1,225 @@ FROM ubuntu:20.04 +ARG DEBIAN_FRONTEND=noninteractive + RUN apt-get update RUN apt-get install -y \ - bison \ - build-essential \ - git \ - vim \ - wget \ - && true + bison \ + build-essential \ + git \ + git-lfs \ + golang-go \ + vim \ + wget \ + autoconf \ + libssl-dev \ + libghc-zlib-dev \ + libcurl4-gnutls-dev \ + libexpat1-dev \ + gettext \ + libpcre3-dev \ + unzip \ + libz-dev \ + make \ + && true # Install shellcheck-0.7.1 RUN cd /root \ - && wget https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz \ - && tar xf shellcheck-v0.7.1.linux.x86_64.tar.xz \ - && mv shellcheck-v0.7.1/shellcheck /usr/local/bin/ \ - && rm -fr shellcheck* \ - && true - -# Build/install bash-3.2.57 -RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-3.2.57.tar.gz \ - && tar -xzf bash-3.2.57.tar.gz \ - && cd bash-3.2.57 \ - && ./configure --prefix=/bash-3.2 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://github.com/koalaman/shellcheck/releases/download/v0.7.1/shellcheck-v0.7.1.linux.x86_64.tar.xz \ + && tar xf shellcheck-v0.7.1.linux.x86_64.tar.xz \ + && mv shellcheck-v0.7.1/shellcheck /usr/local/bin/ \ + && rm -fr shellcheck* \ + && true # Buil/install bash-4.0 RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-4.0.tar.gz \ - && tar -xzf bash-4.0.tar.gz \ - && cd bash-4.0 \ - && ./configure --prefix=/bash-4.0 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://ftp.gnu.org/gnu/bash/bash-4.0.tar.gz \ + && tar -xzf bash-4.0.tar.gz \ + && cd bash-4.0 \ + && ./configure --prefix=/bash-4.0 \ + && make \ + && make install \ + && rm -fr bash* \ + && true # Buil/install bash-4.1 RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-4.1.tar.gz \ - && tar -xzf bash-4.1.tar.gz \ - && cd bash-4.1 \ - && ./configure --prefix=/bash-4.1 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://ftp.gnu.org/gnu/bash/bash-4.1.tar.gz \ + && tar -xzf bash-4.1.tar.gz \ + && cd bash-4.1 \ + && ./configure --prefix=/bash-4.1 \ + && make \ + && make install \ + && rm -fr bash* \ + && true # Buil/install bash-4.2 RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz \ - && tar -xzf bash-4.2.tar.gz \ - && cd bash-4.2 \ - && ./configure --prefix=/bash-4.2 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://ftp.gnu.org/gnu/bash/bash-4.2.tar.gz \ + && tar -xzf bash-4.2.tar.gz \ + && cd bash-4.2 \ + && ./configure --prefix=/bash-4.2 \ + && make \ + && make install \ + && rm -fr bash* \ + && true # Buil/install bash-4.3 RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz \ - && tar -xzf bash-4.3.tar.gz \ - && cd bash-4.3 \ - && ./configure --prefix=/bash-4.3 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://ftp.gnu.org/gnu/bash/bash-4.3.tar.gz \ + && tar -xzf bash-4.3.tar.gz \ + && cd bash-4.3 \ + && ./configure --prefix=/bash-4.3 \ + && make \ + && make install \ + && rm -fr bash* \ + && true # Buil/install bash-4.4 RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-4.4.tar.gz \ - && tar -xzf bash-4.4.tar.gz \ - && cd bash-4.4 \ - && ./configure --prefix=/bash-4.4 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://ftp.gnu.org/gnu/bash/bash-4.4.tar.gz \ + && tar -xzf bash-4.4.tar.gz \ + && cd bash-4.4 \ + && ./configure --prefix=/bash-4.4 \ + && make \ + && make install \ + && rm -fr bash* \ + && true # Buil/install bash-5.0 RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-5.0.tar.gz \ - && tar -xzf bash-5.0.tar.gz \ - && cd bash-5.0 \ - && ./configure --prefix=/bash-5.0 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://ftp.gnu.org/gnu/bash/bash-5.0.tar.gz \ + && tar -xzf bash-5.0.tar.gz \ + && cd bash-5.0 \ + && ./configure --prefix=/bash-5.0 \ + && make \ + && make install \ + && rm -fr bash* \ + && true # Buil/install bash-5.1-rc1 RUN cd /root \ - && wget https://ftp.gnu.org/gnu/bash/bash-5.1-rc1.tar.gz \ - && tar -xzf bash-5.1-rc1.tar.gz \ - && cd bash-5.1-rc1 \ - && ./configure --prefix=/bash-5.1 \ - && make \ - && make install \ - && rm -fr bash* \ - && true + && wget https://ftp.gnu.org/gnu/bash/bash-5.1-rc1.tar.gz \ + && tar -xzf bash-5.1-rc1.tar.gz \ + && cd bash-5.1-rc1 \ + && ./configure --prefix=/bash-5.1 \ + && make \ + && make install \ + && rm -fr bash* \ + && true + +# Buil/install bash-5.2 +RUN cd /root \ + && wget https://ftp.gnu.org/gnu/bash/bash-5.2.tar.gz \ + && tar -xzf bash-5.2.tar.gz \ + && cd bash-5.2 \ + && ./configure --prefix=/bash-5.2 \ + && make \ + && make install \ + && rm -fr bash* \ + && true + +# Buil/install bash-5.3 +RUN cd /root \ + && wget https://ftp.gnu.org/gnu/bash/bash-5.3.tar.gz \ + && tar -xzf bash-5.3.tar.gz \ + && cd bash-5.3 \ + && ./configure --prefix=/bash-5.3 \ + && make \ + && make install \ + && rm -fr bash* \ + && true + + +# Build/install git-2.17 +RUN cd /root \ + && wget --timeout=60 --retry-connrefused --tries=3 https://github.com/git/git/archive/v2.23.4.tar.gz \ + && tar -xzf v2.23.4.tar.gz \ + && cd git-2.23.4 \ + && make configure \ + && ./configure --prefix=/git-2.23 --with-openssl --with-libpcre --with-curl \ + && make all -j$(nproc) \ + && make install \ + && cd /root && rm -fr git* v2.23.4.tar.gz + +# Build/install git-2.25 +RUN cd /root \ + && wget --timeout=60 --retry-connrefused --tries=3 https://github.com/git/git/archive/v2.25.5.tar.gz \ + && tar -xzf v2.25.5.tar.gz \ + && cd git-2.25.5 \ + && make configure \ + && ./configure --prefix=/git-2.25 --with-openssl --with-libpcre --with-curl \ + && make all -j$(nproc) \ + && make install \ + && cd /root && rm -fr git* v2.25.5.tar.gz + +# Build/install git-2.29 +RUN cd /root \ + && wget --timeout=60 --retry-connrefused --tries=3 https://github.com/git/git/archive/v2.29.3.tar.gz \ + && tar -xzf v2.29.3.tar.gz \ + && cd git-2.29.3 \ + && make configure \ + && ./configure --prefix=/git-2.29 --with-openssl --with-libpcre --with-curl \ + && make all -j$(nproc) \ + && make install \ + && cd /root && rm -fr git* v2.29.3.tar.gz + +# Build/install git-2.30 +RUN cd /root \ + && wget --timeout=60 --retry-connrefused --tries=3 https://github.com/git/git/archive/v2.30.9.tar.gz \ + && tar -xzf v2.30.9.tar.gz \ + && cd git-2.30.9 \ + && make configure \ + && ./configure --prefix=/git-2.30 --with-openssl --with-libpcre --with-curl \ + && make all -j$(nproc) \ + && make install \ + && cd /root && rm -fr git* v2.30.9.tar.gz + +# Build/install git-2.40 +RUN cd /root \ + && wget --timeout=60 --retry-connrefused --tries=3 https://github.com/git/git/archive/v2.40.1.tar.gz \ + && tar -xzf v2.40.1.tar.gz \ + && cd git-2.40.1 \ + && make configure \ + && ./configure --prefix=/git-2.40 --with-openssl --with-libpcre --with-curl \ + && make all -j$(nproc) \ + && make install \ + && cd /root && rm -fr git* v2.40.1.tar.gz + +# Build/install git-2.48 +RUN cd /root \ + && wget --timeout=60 --retry-connrefused --tries=3 https://github.com/git/git/archive/v2.48.0.tar.gz \ + && tar -xzf v2.48.0.tar.gz \ + && cd git-2.48.0 \ + && make configure \ + && ./configure --prefix=/git-2.48 --with-openssl --with-libpcre --with-curl \ + && make all -j$(nproc) \ + && make install \ + && cd /root && rm -fr git* v2.48.0.tar.gz + +# Build/install git-2.51 +RUN cd /root \ + && wget --timeout=60 --retry-connrefused --tries=3 https://github.com/git/git/archive/v2.51.0.tar.gz \ + && tar -xzf v2.51.0.tar.gz \ + && cd git-2.51.0 \ + && make configure \ + && ./configure --prefix=/git-2.51 --with-openssl --with-libpcre --with-curl \ + && make all -j$(nproc) \ + && make install \ + && cd /root && rm -fr git* v2.51.0.tar.gz + +# Buil/install bash-5.3 +RUN cd /root \ + && wget https://ftp.gnu.org/gnu/bash/bash-5.3.tar.gz \ + && tar -xzf bash-5.3.tar.gz \ + && cd bash-5.3 \ + && ./configure --prefix=/bash-5.3 \ + && make \ + && make install \ + && rm -fr bash* \ + && true RUN git config --global user.email "you@example.com" \ - && git config --global user.name "Your Name" \ - && git config --global --add safe.directory /git-subrepo/.git \ - && true + && git config --global user.name "Your Name" \ + && true diff --git a/test/error.t b/test/error.t index 8604c1cf..17ffc37e 100644 --- a/test/error.t +++ b/test/error.t @@ -116,11 +116,11 @@ clone-foo-and-bar } { - is "$( + like "$( cd .git catch git subrepo status )" \ - "git-subrepo: Can't 'subrepo status' outside a working tree." \ + "git-subrepo: (Can't 'subrepo status' outside a working tree\.|Not inside a git repository\.)" \ "Error OK: check inside working tree" } @@ -140,11 +140,11 @@ clone-foo-and-bar } { - is "$( + like "$( cd lib catch git subrepo status )" \ - "git-subrepo: Need to run subrepo command from top level directory of the repo." \ + "git-subrepo: (Need to run subrepo command from top level directory of the repo\.|Not inside a git repository\.)" \ "Error OK: check cwd is at top level" } diff --git a/test/pull.t b/test/pull.t index ed3802b8..f7f1938b 100644 --- a/test/pull.t +++ b/test/pull.t @@ -94,6 +94,6 @@ gitrepo=$OWNER/foo/bar/.gitrepo "$OWNER/foo/pull_failed" } -done_testing # 9 +done_testing teardown diff --git a/test/setup b/test/setup index 079d3549..4c1e977a 100755 --- a/test/setup +++ b/test/setup @@ -5,6 +5,63 @@ git config core.autocrlf input set -e +# Isolate git configuration for tests to ensure consistent behavior +# across different environments and prevent interference from user's +# global git configuration + +# Set up a temporary home directory for git config +TEST_HOME=$(mktemp -d) +export HOME="$TEST_HOME" +TEMP_GIT_CONFIG="$TEST_HOME/.gitconfig" +export GIT_CONFIG_GLOBAL="$TEMP_GIT_CONFIG" +export GIT_CONFIG_SYSTEM=/dev/null + +# Set up minimal git configuration for tests +setup_git_config() { + # Core settings + git config --global user.name "Test User" + git config --global user.email "test@example.com" + # Only set init.defaultBranch if Git supports it (Git 2.28+) + git_version=$(git --version | sed 's/git version //' | head -1) + git_major=$(echo "$git_version" | cut -d. -f1) + git_minor=$(echo "$git_version" | cut -d. -f2) + if [[ $git_major -gt 2 ]] || [[ $git_major -eq 2 && $git_minor -ge 28 ]]; then + git config --global init.defaultBranch "master" + fi + git config --global core.autocrlf input + git config --global core.filemode true + git config --global core.bare false + git config --global core.logallrefupdates true + git config --global core.repositoryformatversion 0 + + # Disable interactive prompts + git config --global advice.detachedHead false + git config --global advice.pushNonFastForward false + git config --global advice.statusHints false + git config --global advice.commitBeforeMerge false + git config --global advice.resolveConflict false + git config --global advice.implicitIdentity false + git config --global advice.rmHints false + + # Merge/pull settings + git config --global merge.tool false + git config --global pull.rebase false + git config --global push.default simple + + # Color settings (disable for consistent output) + git config --global color.ui false + git config --global color.branch false + git config --global color.diff false + git config --global color.status false + + # Security settings + git config --global http.sslverify false + git config --global receive.advertisePushOptions false +} + +# Set up git configuration for tests +setup_git_config + # Set the GIT_SUBREPO_ROOT for testing. source "$PWD"/.rc @@ -34,7 +91,15 @@ mkdir -p "$UPSTREAM" "$OWNER" "$COLLAB" cp -r test/repo/{foo,bar,init} "$UPSTREAM/" -DEFAULTBRANCH=$( git config --global --get init.defaultbranch || true ) +# Check if Git supports init.defaultbranch (Git 2.28+) +git_version=$(git --version | sed 's/git version //' | head -1) +git_major=$(echo "$git_version" | cut -d. -f1) +git_minor=$(echo "$git_version" | cut -d. -f2) +if [[ $git_major -gt 2 ]] || [[ $git_major -eq 2 && $git_minor -ge 28 ]]; then + DEFAULTBRANCH=$( git config --global --get init.defaultbranch || true ) +else + DEFAULTBRANCH="" +fi [[ -z $DEFAULTBRANCH ]] && DEFAULTBRANCH="master" export DEFAULTBRANCH @@ -210,4 +275,6 @@ catch() { teardown() { rm -fr "$TMP" + # Clean up temporary home directory and git config + [[ -n "$TEST_HOME" && -d "$TEST_HOME" ]] && rm -rf "$TEST_HOME" }