Skip to main content
edited title
Link
Rui F Ribeiro
  • 58k
  • 28
  • 156
  • 237

Help with bash, git pre-commit script

One step closer to the solution thanks to @Jesse_b
Source Link
Richard
  • 101
  • 3

The goal is to exit from the script with a non-zero exit code when committing package-lock.json with no associated changes to package.json being committed.

#!/bin/bash

# exits with 1 if there were differences and 0 means no differences
file_changed() {
  git diff --quiet --exit-code "$1"
}

# exits with 1 if no lines were selected, 0 if one or more lines selected, > 1 if error
file_staged() {
  git diff --name-only --cached | grep -q "$1"
}

# package-lock.json has changed and
#   package-lock.json in staged files and
#   package.json not in staged files?
if [[ file_changed "package-lock.json" -eq 1 &&
  file_staged "package-lock.json" -eq 0 &&
  file_staged "package.json" -eq 1 ]]
then
  echo "attempted commit of package-lock.json without changes to package.json!"
  exit 1
fi

I'm fairly certain the problem lies in my files_staged function. When testing file_staged "package-lock.json" -eq 0, I get the expected results. When testing file_staged "package.json" -eq 1, it always fails.

Simplifying the problem, I can never get this condition to trigger when package.json is not in the list of files returned by git diff --name-only --cached:

if file_staged "package.json" -eq 1; then
  echo "got here."
fi

Where am I going wrong?


EDIT

@Jesse_b pointed out that I should be using $() around my function calls so that the numerical comparison operators aren't sent as arguments to the function. The following example still doesn't give the desired result:

if [[ $(file_staged "package.json") -eq 1 ]]; then
  echo "got here."
fi

The goal is to exit from the script with a non-zero exit code when committing package-lock.json with no associated changes to package.json being committed.

#!/bin/bash

# exits with 1 if there were differences and 0 means no differences
file_changed() {
  git diff --quiet --exit-code "$1"
}

# exits with 1 if no lines were selected, 0 if one or more lines selected, > 1 if error
file_staged() {
  git diff --name-only --cached | grep -q "$1"
}

# package-lock.json has changed and
#   package-lock.json in staged files and
#   package.json not in staged files?
if file_changed "package-lock.json" -eq 1 &&
  file_staged "package-lock.json" -eq 0 &&
  file_staged "package.json" -eq 1
then
  echo "attempted commit of package-lock.json without changes to package.json!"
  exit 1
fi

I'm fairly certain the problem lies in my files_staged function. When testing file_staged "package-lock.json" -eq 0, I get the expected results. When testing file_staged "package.json" -eq 1, it always fails.

Simplifying the problem, I can never get this condition to trigger when package.json is not in the list of files returned by git diff --name-only --cached:

if file_staged "package.json" -eq 1; then
  echo "got here."
fi

Where am I going wrong?

The goal is to exit from the script with a non-zero exit code when committing package-lock.json with no associated changes to package.json being committed.

#!/bin/bash

# exits with 1 if there were differences and 0 means no differences
file_changed() {
  git diff --quiet --exit-code "$1"
}

# exits with 1 if no lines were selected, 0 if one or more lines selected, > 1 if error
file_staged() {
  git diff --name-only --cached | grep -q "$1"
}

# package-lock.json has changed and
#   package-lock.json in staged files and
#   package.json not in staged files?
if [[ file_changed "package-lock.json" -eq 1 &&
  file_staged "package-lock.json" -eq 0 &&
  file_staged "package.json" -eq 1 ]]
then
  echo "attempted commit of package-lock.json without changes to package.json!"
  exit 1
fi

I'm fairly certain the problem lies in my files_staged function. When testing file_staged "package-lock.json" -eq 0, I get the expected results. When testing file_staged "package.json" -eq 1, it always fails.

Simplifying the problem, I can never get this condition to trigger when package.json is not in the list of files returned by git diff --name-only --cached:

if file_staged "package.json" -eq 1; then
  echo "got here."
fi

Where am I going wrong?


EDIT

@Jesse_b pointed out that I should be using $() around my function calls so that the numerical comparison operators aren't sent as arguments to the function. The following example still doesn't give the desired result:

if [[ $(file_staged "package.json") -eq 1 ]]; then
  echo "got here."
fi
Source Link
Richard
  • 101
  • 3

Help with bash, git pre-commit script

The goal is to exit from the script with a non-zero exit code when committing package-lock.json with no associated changes to package.json being committed.

#!/bin/bash

# exits with 1 if there were differences and 0 means no differences
file_changed() {
  git diff --quiet --exit-code "$1"
}

# exits with 1 if no lines were selected, 0 if one or more lines selected, > 1 if error
file_staged() {
  git diff --name-only --cached | grep -q "$1"
}

# package-lock.json has changed and
#   package-lock.json in staged files and
#   package.json not in staged files?
if file_changed "package-lock.json" -eq 1 &&
  file_staged "package-lock.json" -eq 0 &&
  file_staged "package.json" -eq 1
then
  echo "attempted commit of package-lock.json without changes to package.json!"
  exit 1
fi

I'm fairly certain the problem lies in my files_staged function. When testing file_staged "package-lock.json" -eq 0, I get the expected results. When testing file_staged "package.json" -eq 1, it always fails.

Simplifying the problem, I can never get this condition to trigger when package.json is not in the list of files returned by git diff --name-only --cached:

if file_staged "package.json" -eq 1; then
  echo "got here."
fi

Where am I going wrong?