Skip to content

Commit

Permalink
refactor(dev): add tasks to ease creating patches (#132)
Browse files Browse the repository at this point in the history
* refactor(dev): add tasks to ease creating patches

- task patch:new to start working on a new patch on top of existing patches
- task patch:edit to change an existing patch on top of previous patches

Signed-off-by: Ivan Mikheykin <ivan.mikheykin@flant.com>
  • Loading branch information
diafour authored Jun 26, 2024
1 parent 1689580 commit 5013b48
Show file tree
Hide file tree
Showing 6 changed files with 307 additions and 0 deletions.
14 changes: 14 additions & 0 deletions docs/internal/cdi_kubevirt_patching.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,20 @@ cd ../../
rm -rf tmp/cdi
```

### Work with patches

Use task to start working on a new patch:

```bash
task patch:new
```

Use task to change an existing patch:

```bash
task patch:edit -- 006-customizer.patch
```


### Porting patches to newer version of CDI

Expand Down
173 changes: 173 additions & 0 deletions hack/patch_helper.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
#!/bin/bash

# Copyright 2024 Flant JSC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Helper to automate some routine operations with patches:
# - Apply all patches in a separate branch to help you make a new patch.
# - Apply patches before some patch to help you change specified patch.
# - Clone and checkout specified repo.
# - Create temporary branches.

set -eu -o pipefail

function usage() {
cat <<EOF
$(basename ${0}) OPTIONS
--repo repo-url Repository to clone, e.g. https://github.com/org/project-name.git
--ref git-reference Repository reference to checkout, branch or tag: main, v1.0.0
--patches-dir dir-path Directory where patches reside: ./patches, /project/patches
--stop-at path|name Helper will stop after applying specified patch.
Specify full path or just a name: 010-some-worthy-fix.patch
EOF
}

function main() {
local REPO
local REF
local PATCHES_DIR
local STOP_AT

while [[ $# -gt 0 ]]; do
case "$1" in
--repo)
shift
if [[ $# -ne 0 ]]; then
REPO="${1}"
fi
;;
--ref)
shift
if [[ $# -ne 0 ]]; then
REF="${1}"
fi
;;
--patches-dir)
shift
if [[ $# -ne 0 ]]; then
PATCHES_DIR="${1}"
fi
;;
--stop-at)
shift
if [[ $# -ne 0 ]]; then
STOP_AT="${1}"
fi
;;
*)
echo "ERROR: Invalid argument: $1"
echo
usage
exit 1
;;
esac
shift
done

if [[ -z $REPO ]] ; then
echo "Repository URL is required!" && echo && usage && exit 1
fi
if [[ -z $REF ]] ; then
echo "Ref is required for checkout!" && echo && usage && exit 1
fi
if [[ -z $PATCHES_DIR ]] ; then
echo "Patches directory is required!" && echo && usage && exit 1
fi
if [[ ! -d ${PATCHES_DIR} ]] ; then
echo "'${PATCHES_DIR}' is not a directory!" && echo && usage && exit 1
fi
if [[ -n $STOP_AT ]] ; then
# User specifies stop, but patch is not in patch dir.
stop_at_name=$(basename $STOP_AT)
if ! find ${PATCHES_DIR} -type f -name ${stop_at_name} | grep ${stop_at_name} 2>&1 >/dev/null ; then
echo "Patch ${STOP_AT} not found in '${PATCHES_DIR}' directory" && echo && usage && exit 1
fi
fi

# Transform arguments.
branch=patching/$(date +%Y-%m-%d-%H%M%S)

project=${REPO##*/}
project=${project%.git}

clone_dir=${REF//./-}
clone_dir=__${project}_${clone_dir//\//-}

patches_path=${PATCHES_DIR}
if [[ ${PATCHES_DIR} = ./* || ${PATCHES_DIR} = ../* ]] ; then
patches_path=$(pwd)/${PATCHES_DIR}
fi

# Clone and checkout.
if [[ ! -d ${clone_dir} ]] ; then
git clone --branch ${REF} ${REPO} ${clone_dir}
fi

cd ${clone_dir}

echo "Cleanup workdir for ref $(git name-rev --name-only HEAD) ..."

if ! git diff --exit-code 2>&1 >/dev/null ; then
echo "Workdir is dirty, stash changes ..."
git stash
fi
git reset --hard HEAD

if [[ -n ${STOP_AT} ]] ; then
echo "Create temporary branch ${branch} with patches from ${PATCHES_DIR} until ${STOP_AT} ..."
else
echo "Create temporary branch ${branch} and apply patches from ${PATCHES_DIR} ..."
fi

git checkout ${REF} --no-track -b ${branch}

success=true
stop_at_name=$(basename "${STOP_AT}")
for patch_path in ${patches_path}/*.patch ; do
name=$(basename ${patch_path})
echo -n "Apply ${name} ... "
if git apply --ignore-space-change --ignore-whitespace ${patch_path} ; then
echo OK
if [[ -n ${stop_at_name} && ${stop_at_name} = ${name} ]] ; then
echo "Stop applying patches. NOTE: ${name} is left uncommitted."
break
fi
git add .
git commit -a -m "Apply patch ${name}"
else
echo FAIL
success=false
break
fi
done

if [ "${success}" = false ] ; then
exit 1
fi

echo
echo "Congrats!"
echo "Patches applied, you can make changes in '${clone_dir}' directory and then add a new patch:"
echo "cd ${clone_dir}"
echo "git diff --patch > nnn-my-new-feature.patch"
echo "cd -"
echo "mv ${clone_dir}/nnn-my-new-feature.patch ${PATCHES_DIR}"
echo "git add ${PATCHES_DIR}/nnn-my-new-feature.patch"
}

main "$@"
2 changes: 2 additions & 0 deletions images/cdi-artifact/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore workdirs with CDI sources.
__containerized-data-importer_*
58 changes: 58 additions & 0 deletions images/cdi-artifact/Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
version: "3"

silent: true

env:
CDI_REPO: "https://github.com/kubevirt/containerized-data-importer.git"
CDI_VERSION: "v1.58.0"

tasks:
default:
cmds:
- task: status

status:
cmds:
- |
dir=$(find . -type d -name __containerized-data-importer_\* -depth 1 | head -n1)
if [[ -z $dir ]] ; then
echo "CDI not cloned, run 'task patch:new' to start working on a new patch."
exit 0
fi
cd $dir
git status
cleanup:
cmds:
- |
find . -type d -name __containerized-data-importer_\* -depth 1
read -p "Delete these directories? [y/N] " answer
if [[ "${answer}" != "${answer#[Yy]}" ]] ; then
rm -rf __cdi_*
fi
patch:new:
desc: "Checkout CDI sources, create temp branch, apply all patches as individual commits"
cmds:
- |
../../hack/patch_helper.sh --repo ${CDI_REPO} \
--ref ${CDI_VERSION} \
--patches-dir ./patches
patch:edit:
desc: "Checkout CDI sources, create temp branch, apply patches with commits, leave specified patch uncommitted"
cmds:
- |
patchName="{{.CLI_ARGS}}"
if [[ -z ${patchName} ]] ; then
echo "Specify patch name, e.g.: task patch:edit -- 001-feature-name.patch"
exit 1
fi
../../hack/patch_helper.sh --repo ${CDI_REPO} \
--ref ${CDI_VERSION} \
--patches-dir ./patches \
--stop-at ${patchName}
2 changes: 2 additions & 0 deletions images/virt-artifact/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Ignore workdirs with KubeVirt sources.
__kubevirt_*
58 changes: 58 additions & 0 deletions images/virt-artifact/Taskfile.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
version: "3"

silent: true

env:
KUBEVIRT_REPO: "https://github.com/kubevirt/kubevirt.git"
KUBEVIRT_VERSION: "v1.0.0"

tasks:
default:
cmds:
- task: status

status:
cmds:
- |
dir=$(find . -type d -name __kubevirt_\* -depth 1 | head -n1)
if [[ -z $dir ]] ; then
echo "KubeVirt not cloned, run 'task patch:new' to start working on a new patch."
exit 0
fi
cd $dir
git status
cleanup:
cmds:
- |
find . -type d -name __kubevirt_\* -depth 1
read -p "Delete these directories? [y/N] " answer
if [[ "${answer}" != "${answer#[Yy]}" ]] ; then
rm -rf __kubevirt_*
fi
patch:new:
desc: "Checkout KubeVirt sources, create temp branch, apply all patches as individual commits"
cmds:
- |
../../hack/patch_helper.sh --repo ${KUBEVIRT_REPO} \
--ref ${KUBEVIRT_VERSION} \
--patches-dir ./patches
patch:edit:
desc: "Checkout KubeVirt sources, create temp branch, apply patches with commits, leave specified patch uncommitted"
cmds:
- |
patchName="{{.CLI_ARGS}}"
if [[ -z ${patchName} ]] ; then
echo "Specify patch name, e.g.: task patch:edit -- 001-feature-name.patch"
exit 1
fi
../../hack/patch_helper.sh --repo ${KUBEVIRT_REPO} \
--ref ${KUBEVIRT_VERSION} \
--patches-dir ./patches \
--stop-at ${patchName}

0 comments on commit 5013b48

Please sign in to comment.