Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add packcheck-remote to work with remote repositories directly #36

Merged
merged 2 commits into from
May 26, 2021
Merged
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
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,23 @@ well on the command line. For example,
$ ./packcheck-safe.sh cabal-v2 PATH=/bin:/usr/bin:/opt/ghc/bin
```

## packcheck-remote

`packcheck-remote.sh` is a wrapper over `packcheck.sh`. It allows you to run
packcheck on a remote repository by cloning it locally and optionally merging a
branch into another branch (e.g. merging a PR branch into master).

```
$ ./packcheck-remote.sh --force \
--remote=https://github.com/user/repo \
--checkout=origin/master \
--merge=origin/branch \
--directory=./repo.packcheck \
-- cabal-v2 GHCVER=8.8.3
```

Use `./packcheck-remote.sh --help` for more information.

## Full Reference

Please use `cabal` version 2.4 or later.
Expand Down
208 changes: 208 additions & 0 deletions packcheck-remote.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
#!/usr/bin/env bash

PACKCHECK_DIR=$(dirname "$0")
PACKCHECK_EXE="$PACKCHECK_DIR/packcheck.sh"
PWD="$(pwd)"
DEFAULT_DIRECTORY_NAME="packcheck-remote-work"
DEFAULT_DIRECTORY="$PWD/$DEFAULT_DIRECTORY_NAME"

# $1: msg
show_step() {
echo
echo "--------------------------------------------------"
echo "$1"
echo "--------------------------------------------------"
}

which_cmd() {
hash -r && type -P "$1" || true
}

# $1: executable (eg. git)
require_cmd () {
local cmd_path
cmd_path=$(which_cmd "$1")
if test -z "$cmd_path"
then
echo "Required command [$1] not found in PATH [$PATH]."
exit 1
else
echo "Using [$1] at [$cmd_path]"
fi
}

# $1: command
function run_verbose() {
echo "$1"
bash -c "$1"
}

# $1: Remote repository
# $2: Revision to checkout
# $3: Revision to merge into $2
# $4: Directory to clone into
# $5: Force mode
# $6: Packcheck cli options
try_git_clone_and_merge() {

# Check for prerequisites
require_cmd git

local remote="$1"
local rev="$2"
local merge="$3"
local dir="$4"
local force_mode="$5"
local packcheck_cli_opts="$6"

if test -z "$dir"
then
dir="$DEFAULT_DIRECTORY"
echo "No directory specified to clone to."
echo "Using $dir"
fi

if test -z "$remote"
then
echo "No remote repository provided."
echo "Skipping cloning."
return
fi

if test -z "$rev"
then
echo "No revision given."
echo "Defaulting to 'origin/master'."
rev="origin/master"
fi

if test -d "$dir"
then
echo "$dir already exists"

if [ "$force_mode" == "true" ];
then
echo "Forcing the deletion of the directory."
echo "Removing $dir"
rm -rf "$dir" || exit 1
else
echo "Set the script to force mode to force the deletion."
return
fi
fi

mkdir -p "$dir" || exit 1

run_verbose "git clone $remote $dir" || exit 1

cd "$dir" || exit 1
run_verbose "git branch $rev" || exit 1

if test -n "$merge"
then
# This will fail if there are any merge conflicts
run_verbose "git merge -X theirs $merge --no-edit --commit" || exit 1
fi

show_step "Running packcheck"
# Run packcheck here
run_verbose "$PACKCHECK_EXE $packcheck_cli_opts"
}

# Arguments for the command line
FORCE="false"
REMOTE=""
CHECKOUT=""
MERGE=""
DIRECTORY=""
PACKCHECK_CLI_OPTS_ARR=()
PACKCHECK_CLI_OPTS=""

function run_help() {
local script
script=$(basename "$0")

echo
echo "USAGE: --option[=value]"
echo
echo "-f (or) --force: Puts the script in force mode. This is ideal for CIs."
echo "-h (or) --help: Print help."
echo "--remote: Repository to clone."
echo "--checkout: Revision to checkout. Defaults to 'origin/master'."
echo "--merge: Revision to merge in the checked out branch."
echo "--directory: Directory to clone the repository into."
echo " Defaults to '$DEFAULT_DIRECTORY_NAME' under the present working directory."
echo
echo "All the arguments after '--' are passed to packcheck"
echo

echo
echo "EXAMPLE:"
echo
echo "$script --force \\"
echo " --remote=https://github.com/user/repo \\"
echo " --checkout=origin/master \\"
echo " --merge=origin/branch \\"
echo " --directory=./repo.packcheck \\"
echo " -- cabal-v2 GHCVER=8.8.3"
echo
}

# Program entry point
for i in "$@"
do
case $i in
-f|--force)
FORCE="true"
shift
;;
-h|--help)
run_help
exit 0
;;
--remote=*)
REMOTE="${i#*=}"
shift
;;
--checkout=*)
CHECKOUT="${i#*=}"
shift
;;
--merge=*)
MERGE="${i#*=}"
shift
;;
--directory=*)
DIRECTORY="${i#*=}"
shift
;;
--)
shift
PACKCHECK_CLI_OPTS_ARR=("$@")
break
;;
*)
echo "Unknown argument to packcheck-remote"
run_help
exit 1
;;
esac
done

for i in "${PACKCHECK_CLI_OPTS_ARR[@]}"
do
case $i in
*=*)
key=${1%%=*}
val=${1#*=}
PACKCHECK_CLI_OPTS="$PACKCHECK_CLI_OPTS $key=\"$val\""
shift
;;
*)
PACKCHECK_CLI_OPTS="$PACKCHECK_CLI_OPTS $i"
shift
;;
esac
done

try_git_clone_and_merge "$REMOTE" "$CHECKOUT" "$MERGE" "$DIRECTORY" "$FORCE" "$PACKCHECK_CLI_OPTS"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we just pass "$*" instead of processing $@?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work. a="b c d" would become a=b c d.

23 changes: 21 additions & 2 deletions packcheck-safe.sh
Original file line number Diff line number Diff line change
@@ -1,9 +1,28 @@
#!/usr/bin/env bash

PACKCHECK_DIR=$(dirname $0)
PACKCHECK_DIR=$(dirname "$0")
echo "Running ${PACKCHECK_DIR}/packcheck.sh with clean environment and CHECK_ENV on..."
echo "No environment variables are honored, you have to specifiy ALL the"
echo "parameters explicitly on the command line, including PATH."
echo

/usr/bin/env -i CHECK_ENV=y $(dirname $0)/packcheck.sh $*
PACKCHECK_CLI_OPTS_ARR=("$@")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just quoting $* should work here e.g. /usr/bin/env -i CHECK_ENV=y $(dirname $0)/packcheck.sh "$*"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not work. a="b c d" would become a=b c d.

PACKCHECK_CLI_OPTS=""

for i in "${PACKCHECK_CLI_OPTS_ARR[@]}"
do
case $i in
*=*)
key=${1%%=*}
val=${1#*=}
PACKCHECK_CLI_OPTS="$PACKCHECK_CLI_OPTS $key=\"$val\""
shift
;;
*)
PACKCHECK_CLI_OPTS="$PACKCHECK_CLI_OPTS $i"
shift
;;
esac
done

eval "/usr/bin/env -i CHECK_ENV=y $PACKCHECK_DIR/packcheck.sh $PACKCHECK_CLI_OPTS"
1 change: 1 addition & 0 deletions packcheck.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ extra-source-files:
cabal.project.ci
packcheck.sh
packcheck-safe.sh
packcheck-remote.sh
MAINTAINING.md

source-repository head
Expand Down