Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 46 additions & 5 deletions helper/git-extra-utility
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,56 @@ git_extra_mktemp() {
mktemp -t "$(basename "$0")".XXXXXXX
}

# Determine the default branch name
#
# The detection follows this order:
# 1. Check explicit config 'git-extras.default-branch'
# 2. Remote HEAD auto-detection
# 3. Check git's default branch config 'init.defaultBranch' config
# 4. Common branch detection - Checks if main, master, trunk, development, stable, release, prod, production exist locally
# 5. Fallback to 'main' as last resort
git_extra_default_branch() {
local extras_default_branch init_default_branch
local extras_default_branch init_default_branch remote_default_branch remote_name

# heck git-extras specific config
extras_default_branch=$(git config --get git-extras.default-branch)
init_default_branch=$(git config --get init.defaultBranch)
if [ -n "$extras_default_branch" ]; then
echo "$extras_default_branch"
elif [ -n "$init_default_branch" ]; then
return
fi

# Auto-detect from remote HEAD
# First, try to get a list of remotes
local remotes
remotes=$(git remote 2>/dev/null)
if [ -n "$remotes" ]; then
# Try 'origin' first, then use the first available remote
for remote_name in origin $remotes; do
remote_default_branch=$(git rev-parse --abbrev-ref "$remote_name/HEAD" 2>/dev/null)
if [ -n "$remote_default_branch" ] && [ "$remote_default_branch" != "$remote_name/HEAD" ]; then
# Strip the remote name prefix (e.g., "origin/master" -> "master")
echo "${remote_default_branch#*/}"
return
fi
done
fi

# Check init.defaultBranch config
init_default_branch=$(git config --get init.defaultBranch)
if [ -n "$init_default_branch" ]; then
echo "$init_default_branch"
else
echo "main"
return
fi

# Check if common default branches exist locally
local common_branches="main master trunk development stable release prod production"
for branch in $common_branches; do
if git show-ref --verify --quiet "refs/heads/$branch"; then
echo "$branch"
return
fi
done

# Final fallback
echo "main"
}
243 changes: 243 additions & 0 deletions tests/git-extra-utility.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,243 @@
#!/usr/bin/env bats
# shellcheck shell=bash

source "$BATS_TEST_DIRNAME/test_util.sh"

setup_file() {
test_util.setup_file
}

setup() {
test_util.cd_test
test_util.git_init

# Source the utility file
source "$BATS_TEST_DIRNAME/../helper/git-extra-utility"
}

# Tests for git_extra_mktemp
@test "git_extra_mktemp: creates a temporary file" {
local temp_file
temp_file=$(git_extra_mktemp)

# Check that file was created
[[ -e "$temp_file" ]]

# Cleanup
rm -f "$temp_file"
}

@test "git_extra_mktemp: creates files with unique names" {
local temp_file1 temp_file2
temp_file1=$(git_extra_mktemp)
temp_file2=$(git_extra_mktemp)

# Check that files are different
[[ "$temp_file1" != "$temp_file2" ]]

# Cleanup
rm -f "$temp_file1" "$temp_file2"
}

@test "git_extra_mktemp: temp files are writable" {
local temp_file
temp_file=$(git_extra_mktemp)

# Write to the file
echo "test content" > "$temp_file"

# Verify content
[[ "$(cat "$temp_file")" == "test content" ]]

# Cleanup
rm -f "$temp_file"
}

# Tests for git_extra_default_branch
@test "git_extra_default_branch: respects git-extras.default-branch config" {
git config git-extras.default-branch "custom-branch"

result=$(git_extra_default_branch)

[[ "$result" == "custom-branch" ]]
}

@test "git_extra_default_branch: detects from remote HEAD when origin exists" {
# Setup a remote with main branch (we're already on main from setup)
echo "content" > file.txt
git add file.txt
git commit -m "initial commit"

# Create a bare repo to act as remote
local remote_dir="$BATS_TEST_TMPDIR/remote.git"
git init --bare "$remote_dir"
git remote add origin "$remote_dir"
git push -u origin main
git remote set-head origin main

result=$(git_extra_default_branch)

[[ "$result" == "main" ]]
}

@test "git_extra_default_branch: respects init.defaultBranch config when no remote" {
git config init.defaultBranch "develop"

result=$(git_extra_default_branch)

[[ "$result" == "develop" ]]
}

@test "git_extra_default_branch: detects 'main' branch when it exists locally" {
# We're already on main from setup
result=$(git_extra_default_branch)

[[ "$result" == "main" ]]
}

@test "git_extra_default_branch: detects 'master' branch when it exists locally" {
# Create a new repo with master branch
cd "$BATS_TEST_TMPDIR"
rm -rf test_master
mkdir test_master
cd test_master
git init --initial-branch master
git config user.name 'Name'
git config user.email '[email protected]'
# Need to create a commit so the branch actually exists
echo "content" > file.txt
git add file.txt
git commit -m "initial commit"

source "$BATS_TEST_DIRNAME/../helper/git-extra-utility"
result=$(git_extra_default_branch)

[[ "$result" == "master" ]]
}

@test "git_extra_default_branch: prefers 'main' over 'master' when both exist" {
# First commit to establish main branch
echo "content" > file.txt
git add file.txt
git commit -m "initial commit"

# Create master branch
git checkout -b master
echo "content2" > file2.txt
git add file2.txt
git commit -m "master commit"

# Switch back to main
git checkout main

result=$(git_extra_default_branch)

[[ "$result" == "main" ]]
}

@test "git_extra_default_branch: detects 'trunk' branch" {
# Create a new repo with trunk branch
cd "$BATS_TEST_TMPDIR"
rm -rf test_trunk
mkdir test_trunk
cd test_trunk
git init --initial-branch trunk
git config user.name 'Name'
git config user.email '[email protected]'
# Need to create a commit so the branch actually exists
echo "content" > file.txt
git add file.txt
git commit -m "initial commit"

source "$BATS_TEST_DIRNAME/../helper/git-extra-utility"
result=$(git_extra_default_branch)

[[ "$result" == "trunk" ]]
}

@test "git_extra_default_branch: detects 'development' branch" {
# Create a new repo with development branch
cd "$BATS_TEST_TMPDIR"
rm -rf test_dev
mkdir test_dev
cd test_dev
git init --initial-branch development
git config user.name 'Name'
git config user.email '[email protected]'
# Need to create a commit so the branch actually exists
echo "content" > file.txt
git add file.txt
git commit -m "initial commit"

source "$BATS_TEST_DIRNAME/../helper/git-extra-utility"
result=$(git_extra_default_branch)

[[ "$result" == "development" ]]
}

@test "git_extra_default_branch: falls back to 'main' when no branches exist" {
# Create a completely empty repo
cd "$BATS_TEST_TMPDIR"
rm -rf test_empty
mkdir test_empty
cd test_empty
git init
git config user.name 'Name'
git config user.email '[email protected]'

source "$BATS_TEST_DIRNAME/../helper/git-extra-utility"
result=$(git_extra_default_branch)

[[ "$result" == "main" ]]
}

@test "git_extra_default_branch: git-extras.default-branch takes precedence over remote HEAD" {
# Setup a remote with main branch (we're already on main from setup)
echo "content" > file.txt
git add file.txt
git commit -m "initial commit"

local remote_dir="$BATS_TEST_TMPDIR/remote.git"
git init --bare "$remote_dir"
git remote add origin "$remote_dir"
git push -u origin main
git remote set-head origin main

# Set a different default in config
git config git-extras.default-branch "custom"

result=$(git_extra_default_branch)

# Should use config value, not remote HEAD
[[ "$result" == "custom" ]]
}

@test "git_extra_default_branch: git-extras.default-branch takes precedence over init.defaultBranch" {
git config init.defaultBranch "develop"
git config git-extras.default-branch "custom"

result=$(git_extra_default_branch)

[[ "$result" == "custom" ]]
}

@test "git_extra_default_branch: remote HEAD takes precedence over init.defaultBranch" {
# Setup a remote with main branch
echo "content" > file.txt
git add file.txt
git commit -m "initial commit"

local remote_dir="$BATS_TEST_TMPDIR/remote.git"
git init --bare "$remote_dir"
git remote add origin "$remote_dir"
git push -u origin main
git remote set-head origin main

# Set a different default in init config
git config init.defaultBranch "develop"

result=$(git_extra_default_branch)

# Should use remote HEAD, not init.defaultBranch
[[ "$result" == "main" ]]
}
Loading