Permalink
Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
executable file 255 lines (214 sloc) 5.73 KB
#!/bin/bash
set -ef
if [ $# -eq 0 ]; then
set -- -h
fi
OPTS_SPEC="\
git playback file1 file2 ...
Use left and right arrows to navigate the output.
--
h,help show the help
s,start= specify start revision. Default: root commit
e,end= specify end revision. Default: current branch
t,style= specify style to be used in output
l,stylelist list all available styles
n,no-message don't output commit message
"
eval "$(echo "$OPTS_SPEC" | git rev-parse --parseopt -- "$@" || echo exit $?)"
get_git_branch() {
git branch 2>/dev/null | grep -e ^* | tr -d \*
}
get_root_commit() {
git rev-list --max-parents=0 HEAD 2>/dev/null | tr -d \*
}
files=()
output_file='playback.html'
start_revision=`get_root_commit`
end_revision=`get_git_branch`
style='default'
available_styles=(default dark far idea sunburst zenburn vs ascetic magula github googlecode brown_paper school_book ir_black solarized_dark solarized_light arta monokai xcode pojoaque tomorrow tomorrow-night tomorrow-night-blue tomorrow-night-eighties tomorrow-night-bright)
message=true
while [ $# -gt 0 ]; do
opt="$1"
shift
case "$opt" in
-s) start_revision="$1"; shift;;
-e) end_revision="$1"; shift;;
-t) style="$1"; shift;;
-l) echo ${available_styles[@]}; exit;;
-n) message=false ;;
*) files+=("$1") ;;
esac
done
is_style_available() {
for i in ${available_styles[@]}; do
if [ $i == $1 ]; then
return 1
fi
done
return 0
}
if is_style_available $style; then
echo "Style is not available: ${style}. You can list available styles with --stylelist."
exit 1
fi
source_file="${BASH_SOURCE[0]}"
while [ -h "$source_file" ]; do
source_file="$(readlink "$source_file")";
done
script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd -P "$(dirname "$source_file")" && pwd)"
unset source_file
js=`cat "${script_dir}/git-playback.js/playback.js"`
jquery=`cat "${script_dir}/git-playback.js/jquery.js"`
highlight=`cat "${script_dir}/git-playback.js/highlight.js"`
css=`cat "${script_dir}/git-playback.css/playback.css"`
stylecss=`cat "${script_dir}/git-playback.css/${style}.css"`
htmlStart="<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='utf-8'>
<title>Git Playback</title>
<style type='text/css'>${css}</style>
<style type='text/css'>${stylecss}</style>
</head>
<body>
<div id='playback'>
<div class='container'>"
htmlEnd="</div>
</div>
<script type='text/javascript'>${jquery}</script>
<script type='text/javascript'>${highlight}</script>
<script type='text/javascript'>${js}</script>
<script>
jQuery(document).ready(function(){
jQuery('#playback').playback();
hljs.initHighlightingOnLoad();
var background = jQuery('pre code').css('background-color');
jQuery('body').css('background-color', background);
var foreground = jQuery('code > span.keyword').css('color');
jQuery('pre.message').css('border-color', foreground);
});
</script>
</body>
</html>"
foreach_git_revision() {
command=$1
revisions=`git rev-list --reverse ${end_revision} ^${start_revision}`
for revision in $revisions; do
git checkout --quiet $revision
eval $command
git reset --hard
done
git checkout --quiet $end_revision
}
has_files() {
for file in ${files[@]}
do
if [ -f $file ] && [ -s $file ]; then
return 0
else
return 1
fi
done
}
write_playback_opening_tag() {
echo '<div class="playback"><ul>' >> $output_file
}
write_playback_closing_tag() {
echo '</ul></div>' >> $output_file
}
write_code_opening_tag() {
echo -e '<li><pre><code>\c' >> $output_file
}
write_code_closing_tag() {
echo -e '</code></pre></li>\c' >> $output_file
}
write_file() {
if [ -f $1 ]; then
eval "$(cat $1 >> $output_file)"
fi
}
write_diff() {
if [ -f $1 ]; then
line_count="$(git diff --unified=999999 HEAD~1 $1 | grep '[^ ]' | wc -l)"
if [ $line_count -eq 0 ]; then
eval "$(cat $1 >> $output_file)"
else
eval "$(git diff --unified=999999 HEAD~1 $1 | read_diff >> $output_file)"
fi
fi
}
write_commit_message() {
if $message; then
echo '<pre class="message" style="border-bottom: solid;border-bottom-width: 1px"><code class="no-highlight">' >> $output_file
eval "$(git log -1 --pretty=format:'<span>%h</span><span>: </span><span class="keyword">%s</span>' --abbrev-commit >> $output_file)"
echo '</code></pre>' >> $output_file
fi
}
write_start_revision() {
git checkout --quiet $start_revision
if has_files; then
write_playback_opening_tag
write_commit_message
for file in ${files[@]}
do
write_code_opening_tag
write_file $file
write_code_closing_tag
done
write_playback_closing_tag
fi
git reset --hard
}
write_revision() {
if has_files; then
write_playback_opening_tag
write_commit_message
for file in ${files[@]}
do
write_code_opening_tag
write_diff $file
write_code_closing_tag
done
write_playback_closing_tag
fi
}
read_diff() {
OIFS=$IFS
IFS=''
read -r s
while [[ $? -eq 0 ]]
do
if [[ $s == diff* ]] ||
[[ $s == +++* ]] ||
[[ $s == ---* ]] ||
[[ $s == @@* ]] ||
[[ $s == index* ]]; then
class='none'
elif [[ $s == +* ]]; then
s=${s#+}
class='new'
elif [[ $s == -* ]]; then
s=${s#-}
class='old'
else
s=${s# }
class=
fi
if [[ "$class" == 'none' ]]; then
class='none'
elif [[ "$class" ]]; then
echo -E '<div class="'${class}'">'${s}
echo -e '</div>\c'
else
echo -E $s
fi
read -r s
done
IFS=$OIFS
}
rm -f $output_file
echo $htmlStart >> $output_file
write_start_revision
foreach_git_revision write_revision
echo $htmlEnd >> $output_file