Skip to content
Open
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
60 changes: 44 additions & 16 deletions git-backport-diff
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ def_pause='y'
def_sensitivity=0
def_summary='n'

if [ -z "${DIFFOPTS+x}" ]; then
DIFFOPTS=
fi

upstream=`git config backport-diff.upstream || true`
diffprog=`git config backport-diff.diffprog || true`
range=`git config backport-diff.range || true`
Expand Down Expand Up @@ -126,7 +130,9 @@ usage() {
echo " git config backport-diff.summary"
}

while getopts ":r:u:nd:phs:S" opt
declare -A aliases

while getopts ":r:u:nd:phs:Sa:" opt
do
case $opt in
r) range=$OPTARG
Expand All @@ -149,6 +155,9 @@ do
;;
S) summary='y'
;;
a) IFS='=' read -ra a <<< "$OPTARG"
aliases[${a[0]}]=${a[1]}
;;
h) usage
exit
;;
Expand Down Expand Up @@ -205,7 +214,7 @@ elif git show-ref --quiet --verify refs/remotes/${upstream}
then
upstream_valid='y'
# commit id
elif git rev-list --max-count=1 --quiet $upstream >/dev/null 2>&1
elif git rev-list --max-count=1 --quiet $upstream -- >/dev/null 2>&1
then
upstream_valid='y'
fi
Expand All @@ -225,31 +234,50 @@ compare_git()
while read hashsubj
do
let cnt=$cnt+1;
subj=${hashsubj:40}
newsubj=${hashsubj:40}
subj=$newsubj
if [ -n "${aliases[$subj]+_}" ]
then
subj=${aliases[$subj]}
fi

# We need to direct the git-log output through a FIFO so we
# get a git-log job that we can kill once we have found our
# match
git_fifo=$(mktemp -u --tmpdir 'backport-diff.XXXXXX')
mkfifo "$git_fifo"

downhash=${hashsubj:0:40}
# A little bit hackish, but find the match by looking at upstream
# subject lines, and using the newest one. Not all backports contain
# the phrase "cherry-pick", so we can't really try and find the
# upstream hash from that...
uphash=""
git log $upstream --pretty=tformat:"%H%s" --fixed-strings --grep="${subj}" -- >"$git_fifo" &
job_id=$(jobs -l | grep "\<$!\>" | sed -e 's/[^\[]*\[\([^\]]*\)\].*/\1/')
while read uphashsubj
do
if [[ "${uphashsubj:40}" == "$subj" ]]
then
uphash=${uphashsubj:0:40}
break
fi
done < <(git log $upstream --pretty=tformat:"%H%s" --fixed-strings --grep="${subj}")
done <"$git_fifo"

# Ignore errors
kill %$job_id &>/dev/null || true
wait &> /dev/null
rm -f "$git_fifo"

if [[ -n "$uphash" ]]
then
numdiff=`diff -u <(git diff $uphash^! |egrep ^[-+])\
<(git diff $downhash^! |egrep ^[-+])\
| egrep '^[-+]' | egrep -v '^[-+]{3}' |wc -l || true`
numdiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^! |grep -E ^[-+])\
<(git diff --diff-algorithm=patience $DIFFOPTS $downhash^! |grep -E ^[-+])\
| grep -E '^[-+]' | grep -E -v '^[-+]{3}' |wc -l || true`
# for contextual diff checking, we will ignore hashes and line number offsets
condiff=`diff -u <(git diff $uphash^\! |sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\
<(git diff $downhash^\!|sed -e s/^@@.*@@//g |egrep -v ^index |egrep -v ^diff)\
| egrep '^[-+]' | egrep -v '^[-+]{3}'|wc -l || true`
condiff=`diff -u <(git diff --diff-algorithm=patience $DIFFOPTS $uphash^\! |sed -e s/^@@.*@@//g |grep -E -v ^index |grep -E -v ^diff)\
<(git diff --diff-algorithm=patience $DIFFOPTS $downhash^\!|sed -e s/^@@.*@@//g |grep -E -v ^index |grep -E -v ^diff)\
| grep -E '^[-+]' | grep -E -v '^[-+]{3}'|wc -l || true`
f="-"
c="-"
if [[ $sensitivity -gt 1 ]]
Expand All @@ -270,22 +298,22 @@ compare_git()
then
f=${bold}F${reset}
showdiff=1
printf "%03d/${total}:[${bold}%04d${reset}] [${f}${c}] ${bold}${color4}'%s'${reset}\n" $cnt $numdiff "$subj"
printf "%03d/${total}:[${bold}%04d${reset}] [${f}${c}] ${bold}${color4}'%s'${reset}\n" $cnt $numdiff "$newsubj"
else
printf "%03d/$total:[----] [${f}${c}] '%s'\n" $cnt "$subj"
printf "%03d/$total:[----] [${f}${c}] '%s'\n" $cnt "$newsubj"
fi
if [[ $showdiff -eq 1 ]]
then
if [[ $diffprog == "meld" ]]
then
label="--label=\"Patch #$cnt: $subj\" --label=\" \""
label="--label=\"Patch #$cnt: $newsubj\" --label=\" \""
fi
subjlist[$cnt]=$subj
exe[$cnt]="${label} <(git show $uphash^!) <(git show $downhash^!) 2>/dev/null"
subjlist[$cnt]=$newsubj
exe[$cnt]="${label} <(git show $DIFFOPTS $uphash^!) <(git show $DIFFOPTS $downhash^!) 2>/dev/null"
shortexe[$cnt]="<(git show ${uphash:0:7}^\!) <(git show ${downhash:0:7}^\!)"
fi
else
printf "%03d/$total:[${bold}${color1}down${reset}] ${bold}${color4}'%s'${reset}\n" $cnt "$subj"
printf "%03d/$total:[${bold}${color1}down${reset}] ${bold}${color4}'%s'${reset}\n" $cnt "$newsubj"
fi
done < <(git log --pretty=tformat:"%H%s" --reverse $range)
}
Expand Down
90 changes: 90 additions & 0 deletions git-submit
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
#!/usr/bin/ruby

require 'shellwords'

def die(msg, hint=nil)
$stderr.puts("\033[31;1m#{msg}\033[0m")
if hint
$stderr.puts("\033[1mHint: #{hint}\033[0m")
end
exit 1
end

def run(cmd)
puts("\033[1m$ #{cmd}\033[0m")
$stdout.write("OK? [y/n] ")
$stdout.flush
if gets.strip.downcase != 'y'
puts('(Aborting)')
exit 0
end
system(cmd)
end

def branch_exists?(name)
!`git branch --list #{name.shellescape}`.strip.empty?
end

upstream_branch = 'main'
if !branch_exists?(upstream_branch)
upstream_branch = 'master'
end
if !branch_exists?(upstream_branch)
die('Found neither “main” nor “master”')
end

next_branch = `git branch --show-current`.strip
if next_branch.empty?
die('Not on any branch')
end

m = next_branch.match(/^(.*)-next$/)
if !m
die("Current branch (#{next_branch}) does not match the pattern `${topic}-next`")
end
base_branch = m[1]

if !system("git merge-base --is-ancestor #{upstream_branch} #{next_branch}")
die("Upstream base branch #{upstream_branch} is not an ancestor of #{next_branch}")
end

remote = `git config get branch.#{base_branch.shellescape}.remote`.strip
if remote.empty?
die("Base topic branch #{base_branch} has no remote info set", "Use git branch --set-upstream-to=${remote}/#{base_branch}")
end

max_topic_ver = `git branch --color=never --list #{"#{base_branch}-v*".shellescape} | sort | tail -n 1`.strip.sub("#{base_branch}-v", '')
if max_topic_ver.empty?
max_topic_ver = 0
else
max_topic_ver = Integer(max_topic_ver)
end
new_topic_ver = max_topic_ver + 1

puts <<EOF
Here’s the plan (currently on branch \033[1m#{next_branch}\033[0m):
· Go to branch \033[1m#{base_branch}\033[0m
· Reset \033[1m#{base_branch}\033[0m to \033[1m#{next_branch}\033[0m
· Review backport-diff of \033[1m#{upstream_branch}..#{base_branch}\033[0m vs. \033[1m#{remote}/#{base_branch}\033[0m
· Force-push \033[1m#{base_branch}\033[0m to \033[1m#{remote}/#{base_branch}\033[0m
· Create \033[1m#{base_branch}-v#{new_topic_ver}\033[0m from \033[1m#{base_branch}\033[0m
· Return to \033[1m#{next_branch}\033[0m

EOF

run("git checkout #{base_branch.shellescape}")
run("git reset --hard #{next_branch.shellescape}")
run("git backport-diff -r #{upstream_branch.shellescape}..#{base_branch.shellescape} -u #{remote.shellescape}/#{base_branch.shellescape}")

puts
puts("\033[1mAre those changes OK?\033[0m")
$stdout.write("[y/n] ")
$stdout.flush
if gets.strip.downcase != 'y'
puts('(Aborting)')
exit 0
end

run("git push -f #{remote.shellescape} #{base_branch.shellescape}")
run("git branch #{"#{base_branch}-v#{new_topic_ver}".shellescape}")
run("git checkout #{next_branch}")
26 changes: 26 additions & 0 deletions github-fetch-mr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/bin/bash

set -e

mr=$1
remote="${2:-origin}"

if [[ ! $mr =~ ^[0-9]+$ || $3 != "" ]]; then
echo "Usage: $0 <MR ID> [remote]" >&2
exit 1
fi

if [ -n "$2" ]; then
infix="$2-"
else
infix=""
fi

max_ver=$(git branch --list "mr-$infix$mr-v*" | sort | tail -n 1 | sed -e "s/^\*\? *mr-$infix$mr-v//")
branch="mr-$infix$mr-v$((max_ver + 1))"
cmd="git fetch $remote pull/$mr/head:$branch"

echo "\$ $cmd"
$cmd

git checkout $branch
20 changes: 20 additions & 0 deletions gitlab-fetch-mr.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#!/bin/bash

set -e

mr=$1
remote="${2:-origin}"

if [[ ! $mr =~ ^[0-9]+$ || $3 != "" ]]; then
echo "Usage: $0 <MR ID> [remote]" >&2
exit 1
fi

max_ver=$(git branch --list "mr-$mr-v*" | grep "mr-$mr-v[0-9]\\+$" | sort | tail -n 1 | sed -e "s/^\*\? *mr-$mr-v//")
branch="mr-$mr-v$((max_ver + 1))"
cmd="git fetch $remote merge-requests/$mr/head:$branch"

echo "\$ $cmd"
$cmd

git checkout $branch