Created
July 24, 2016 16:21
-
-
Save bdrewery/e934883c917e552067be991c64bc06ff to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /bin/sh | |
# :vim setf sh: | |
# | |
# Copyright (c) 2013 Bryan Drewery <[email protected]> | |
# All rights reserved. | |
# | |
# Redistribution and use in source and binary forms, with or without | |
# modification, are permitted provided that the following conditions | |
# are met: | |
# 1. Redistributions of source code must retain the above copyright | |
# notice, this list of conditions and the following disclaimer. | |
# 2. Redistributions in binary form must reproduce the above copyright | |
# notice, this list of conditions and the following disclaimer in the | |
# documentation and/or other materials provided with the distribution. | |
# | |
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
# SUCH DAMAGE. | |
set -e | |
set -x | |
usage() { | |
cat << EOF | |
git fossil <cmd> [args] | |
rebase -- Rebase current branch on the latest fossil version | |
dcommit -- Commit changes upstream | |
-n: Dry-mode, show what would be done | |
EOF | |
} | |
stash() { | |
[ -z "$(git status --porcelain)" ] && return 0 | |
git stash | |
STASHED=1 | |
} | |
unstash() { | |
if [ ${STASHED:-0} -eq 1 ]; then | |
git stash pop | |
STASHED=0 | |
fi | |
} | |
check_untracked_files() { | |
if [ -n "$(git ls-files --other --exclude-standard)" ]; then | |
echo "Error: UNTRACKED FILES!" >&2 | |
git ls-files --other --exclude-standard | |
exit 1 | |
fi | |
} | |
exit_handler() { | |
unstash | |
} | |
trap exit_handler EXIT | |
cmd_dcommit() { | |
local current_branch merge_base hash | |
check_untracked_files | |
current_branch="$(git rev-parse --abbrev-ref HEAD)" | |
merge_base=$(git merge-base ${current_branch} fossil) | |
cmd_rebase | |
set -e | |
git rev-list --reverse ${merge_base}..HEAD | while read hash; do | |
[ $DRY_MODE -eq 0 ] && git checkout ${hash} | |
log=$(git log -1 --pretty="format:%B" ${hash}) | |
if [ $DRY_MODE -eq 1 ]; then | |
echo "Would commit ${hash}: " | |
echo "${log}" | sed -e 's,^, ,' | |
git show --name-status -M -C --pretty="format:" ${hash} | |
else | |
git show --name-status -M -C --pretty="format:" \ | |
${hash} | while read status file newfile; do | |
case ${status} in | |
A) | |
fossil add "${file}" | |
;; | |
C*) | |
fossil cp "${file}" \ | |
"${newfile}" | |
;; | |
D) | |
fossil rm "${file}" | |
;; | |
R*) | |
fossil mv "${file}" \ | |
"${newfile}" | |
#mv "${file}" "${newfile}" | |
;; | |
M) | |
touch "${file}" | |
;; | |
*) | |
;; | |
esac | |
done | |
fossil status | |
yes|fossil commit -m "${log}" | |
update_fossil_branch force | |
#merge_base=$(git merge-base HEAD fossil) | |
#git checkout ${current_branch} | |
#git rebase --onto fossil ${merge_base} | |
fi | |
done | |
git checkout ${current_branch} | |
git reset --hard fossil | |
} | |
update_fossil_branch() { | |
local current_branch fossil_hash force=0 | |
[ $# -eq 1 ] && force=1 | |
current_branch="$(git rev-parse --abbrev-ref HEAD)" | |
git checkout -f fossil | |
fossil update | |
fossil revert >/dev/null 2>&1 | |
#if [ $force -eq 1 ] || [ -n "$(fossil diff --brief)" ]; then | |
if [ $force -eq 1 ] || [ -n "$(git status --porcelain)" ]; then | |
fossil_hash="$(fossil status | | |
awk '$1 == "checkout:" {print $2}')" | |
fossil_url="$(fossil remote-url)" | |
fossil clean -f | |
git add -A . | |
### XXX: Need actual commit message in here from fossil | |
### XXX: Need to use git-notes for this crap. | |
git commit -a --author="Git Fossil <[email protected]>" \ | |
-m "Sync with fossil" | |
git notes add -m "${fossil_url}@${fossil_hash}" HEAD | |
fi | |
git checkout -f ${current_branch} | |
} | |
cmd_rebase() { | |
local current_branch merge_base fossil_url | |
check_untracked_files | |
stash | |
update_fossil_branch | |
merge_base=$(git merge-base HEAD fossil) | |
git rebase --onto fossil ${merge_base} | |
} | |
DRY_MODE=0 | |
cmd="$1" | |
shift | |
while getopts "n" FLAG; do | |
case "${FLAG}" in | |
n) | |
DRY_MODE=1 | |
;; | |
esac | |
done | |
shift $((OPTIND-1)) | |
case ${cmd} in | |
dcommit) | |
cmd_dcommit "$@" | |
;; | |
rebase) | |
cmd_rebase "$@" | |
;; | |
*) | |
usage | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment