Skip to content

Instantly share code, notes, and snippets.

@hchbaw
Created October 14, 2011 15:25
Show Gist options
  • Save hchbaw/1287423 to your computer and use it in GitHub Desktop.
Save hchbaw/1287423 to your computer and use it in GitHub Desktop.
#!/bin/zsh
dashless=${${0:t}/-/ }
USAGE="[-f|--force] [-s|--stashify] <commit>..."
LONG_USAGE="$dashless <commit>...
save <commit>... in the stash ref namespace.
Basically $dashless deals with stashed <commit> but it could be:
[-f|--force] force operation
[-s|--stashify][-2] convert existing <commit> as if it were stashed.
[-2] means create stash as the base commit <commit>~2,
<commit>~1 as the index and <commit> as the work tree.
default: base commit <commit>~1, and <commit> as index
and work tree. (In other words, assume index and work
tree are being kept intact.)"
typeset -a _A; set -A _A "$@"
_0="${0-}"
() {
() {
local 0=${_0}
set -- "${_A[@]}"
emulate -L sh
OPTIONS_SPEC=
SUBDIRECTORY_OK=t
. git-sh-setup
require_work_tree
cd_to_toplevel
}
eval "die_with_status () { ${functions[die_with_status]//status/_status} }"
}
git-stash~ () {
local stashproc="$1"; shift
local stashishp="$1"; shift
local gitstash_refstash=refs/stash
local c=; for c in "$@"; do
git-stash~~ $stashproc $stashishp "$c" git-stash~~-update-ref
done
}
git-stash~~ () {
local stashf="$1"
local stashp="$2"
local commitish="$3"
local k="$4"
setopt localoptions no_ksharrays no_kshzerosubscript extendedglob
local commit="$(git rev-parse "$commitish" 2> /dev/null)" ||
die "commit '$commitish' doesn't exist"
"$stashf" "$stashp" "$commit" "$commitish" "$k"
}
git-stash~~-update-ref () {
local stashmsg="$1"
local stashcommit="$2"
local commit="$3"
local abbrevcommit="$(git rev-parse --short $commit)"
: >>"$GIT_DIR/logs/$gitstash_refstash"
git update-ref -m "$stashmsg" $gitstash_refstash $stashcommit ||
die "Cannot save the commit status"
say Saved stashish commit $abbrevcommit "$stashmsg"
}
git-stash~-restash () {
local stashp="$1"
local commit="$2"
local commitish="$3"
local k="$4"
local -a cs; : ${(A)cs::=${(@f)"$(git log -3 -s --format=%s ${commit})"}}
"$stashp" "$cs[@]" && {
"$k" "$cs[1]" "$commit" "$commit"
} || die "'$commitish' doesn't seem like stash"
}
git-stash~-stashify-1-raw () {
local commit="$1"
local k="$2"
local kk="$3"
local wtree= icommit= imesg= bcommit= bmesg=
local -a tmp;
git-stash~-stashify-fetch-commit-or-lose tmp '%H%n%s\ \(%h\)%n%T' "${commit}"
icommit="$tmp[2]"; imesg="$tmp[3]"; wtree="$tmp[4]"
# TODO: tweak the commit here.
git-stash~-stashify-fetch-commit-or-lose tmp '%H%n%s\ \(%h\)' "${commit}~1"
bcommit="$tmp[2]"; bmesg="$tmp[3]"
"$k" "WIP $imesg; $bmesg" $wtree $bcommit $icommit "$kk"
}
git-stash~-stashify-2-raw () {
local commit="$1"
local k="$2"
local kk="$3"
local wtree= wmesg= icommit= imesg= bcommit= bmesg=
local -a tmp;
# TODO: tweak the commit.
git-stash~-stashify-fetch-commit-or-lose tmp '%T%n%s\ \(%h\)' ${commit}
wtree="$tmp[2]"; wmesg="$tmp[3]"
git-stash~-stashify-fetch-commit-or-lose tmp '%H%n%s\ \(%h\)' "${commit}~1"
icommit="$tmp[2]"; imesg="$tmp[3]"
git-stash~-stashify-fetch-commit-or-lose tmp '%H%n%s\ \(%h\)' "${commit}~2"
bcommit="$tmp[2]"; bmesg="$tmp[3]"
"$k" "WIP $wmesg; $imesg; $bmesg" $wtree $bcommit $icommit "$kk"
}
git-stash~-stashify-fetch-commit-or-lose () {
local place="$1"
local fmt="$2"
local c="$3"
: ${(PA)place::=${(@f)"$(git rev-list --no-walk --format=${(Q)fmt} $c)"}}
[[ ${${(PA)place}[1]} == (#s)commit\ * ]] ||
die "Cannot fetch the commit '$c'."
}
git-stash~-stashify-k () {
local stashmsg="$1"
local wtree="$2"
local bcommit="$3"
local icommit="$4"
local k="$5"
local commitmaybe=$(echo "$stashmsg"|
git commit-tree $wtree -p $bcommit -p $icommit) ||
die "Cannot record stashified commit"
"$k" "$stashmsg" "$commitmaybe" "$commit"
}
def-git-stash~-stashify-n () {
eval ${${:-'
git-stash~-stashify-_N_ () {
local _stashp="$1"
local commit="$2"
local _commitish="$3"
local k="$4"
git-stash~-stashify-_N_-raw "$commit" git-stash~-stashify-k "$k"
}
'}//_N_/$1}
}
def-git-stash~-stashify-n 2
def-git-stash~-stashify-n 1
git-stash~-stashish-p () {
# XXX: This may not be accurate though
[[ -n "${1-}" ]] && [[ "${1}" == (#s)WIP\ on* ]] &&
[[ -n "${2-}" ]] && [[ "${2}" == (#s)index\ on* ]] &&
[[ -n "${3-}" ]]
}
zparseopts -E -D \
f=force -force=force s=stashify -stashify=stashify 2=grandparentasbase
(($#==0)) && usage
if [[ -z "${force}" ]]; then
set -- git-stash~-stashish-p "$@"
else
set -- : "$@"
fi
if [[ -z "${stashify}" ]]; then
set -- git-stash~-restash "$@"
else
if [[ -z "${grandparentasbase}" ]]; then
set -- git-stash~-stashify-1 "$@"
else
set -- git-stash~-stashify-2 "$@"
fi
fi
git-stash~ "$@"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment