Commit a46ec165 authored by John Koleszar's avatar John Koleszar
Browse files

FTFY: support wordwrapping commit messages

It's common for commit messages to be wrapped at odd places. git-gui
is often to blame. Adds support for automatically fixing up these
messages if running ftfy --amend, and adds a new option --msg-only for
fixing only the commit message.

Change-Id: Ia7ea529f8cb7395d34d9b39f1192598e9a1e315b
Showing with 119 additions and 21 deletions
#!/bin/sh #!/bin/sh
self="$0" self="$0"
dirname_self=$(dirname "$self")
usage() { usage() {
cat <<EOF >&2 cat <<EOF >&2
...@@ -9,9 +10,13 @@ This script applies a whitespace transformation to the commit at HEAD. If no ...@@ -9,9 +10,13 @@ This script applies a whitespace transformation to the commit at HEAD. If no
options are given, then the modified files are left in the working tree. options are given, then the modified files are left in the working tree.
Options: Options:
-h, --help Shows this message
-n, --dry-run Shows a diff of the changes to be made. -n, --dry-run Shows a diff of the changes to be made.
--amend Squashes the changes into the commit at HEAD --amend Squashes the changes into the commit at HEAD
This option will also reformat the commit message.
--commit Creates a new commit containing only the whitespace changes --commit Creates a new commit containing only the whitespace changes
--msg-only Reformat the commit message only, ignore the patch itself.
EOF EOF
rm -f ${CLEAN_FILES} rm -f ${CLEAN_FILES}
exit 1 exit 1
...@@ -34,7 +39,7 @@ vpx_style() { ...@@ -34,7 +39,7 @@ vpx_style() {
apply() { apply() {
patch -p1 < "$1" [ $INTERSECT_RESULT -ne 0 ] && patch -p1 < "$1"
} }
...@@ -59,8 +64,28 @@ EOF ...@@ -59,8 +64,28 @@ EOF
} }
show_commit_msg_diff() {
if [ $DIFF_MSG_RESULT -ne 0 ]; then
log "Modified commit message:"
diff -u "$ORIG_COMMIT_MSG" "$NEW_COMMIT_MSG" | tail -n +3
fi
}
amend() { amend() {
git commit -a --amend -C HEAD show_commit_msg_diff
if [ $DIFF_MSG_RESULT -ne 0 ] || [ $INTERSECT_RESULT -ne 0 ]; then
git commit -a --amend -F "$NEW_COMMIT_MSG"
fi
}
diff_msg() {
git log -1 --format=%B > "$ORIG_COMMIT_MSG"
"${dirname_self}"/wrap-commit-msg.py \
< "$ORIG_COMMIT_MSG" > "$NEW_COMMIT_MSG"
cmp -s "$ORIG_COMMIT_MSG" "$NEW_COMMIT_MSG"
DIFF_MSG_RESULT=$?
} }
...@@ -68,7 +93,10 @@ amend() { ...@@ -68,7 +93,10 @@ amend() {
ORIG_DIFF=orig.diff.$$ ORIG_DIFF=orig.diff.$$
MODIFIED_DIFF=modified.diff.$$ MODIFIED_DIFF=modified.diff.$$
FINAL_DIFF=final.diff.$$ FINAL_DIFF=final.diff.$$
ORIG_COMMIT_MSG=orig.commit-msg.$$
NEW_COMMIT_MSG=new.commit-msg.$$
CLEAN_FILES="${ORIG_DIFF} ${MODIFIED_DIFF} ${FINAL_DIFF}" CLEAN_FILES="${ORIG_DIFF} ${MODIFIED_DIFF} ${FINAL_DIFF}"
CLEAN_FILES="${CLEAN_FILES} ${ORIG_COMMIT_MSG} ${NEW_COMMIT_MSG}"
# Preconditions # Preconditions
[ $# -lt 2 ] || usage [ $# -lt 2 ] || usage
...@@ -95,28 +123,30 @@ done ...@@ -95,28 +123,30 @@ done
git diff --no-color --no-ext-diff > "${MODIFIED_DIFF}" git diff --no-color --no-ext-diff > "${MODIFIED_DIFF}"
# Intersect the two diffs # Intersect the two diffs
$(dirname ${self})/intersect-diffs.py \ "${dirname_self}"/intersect-diffs.py \
"${ORIG_DIFF}" "${MODIFIED_DIFF}" > "${FINAL_DIFF}" "${ORIG_DIFF}" "${MODIFIED_DIFF}" > "${FINAL_DIFF}"
INTERSECT_RESULT=$? INTERSECT_RESULT=$?
git reset --hard >/dev/null git reset --hard >/dev/null
if [ $INTERSECT_RESULT -eq 0 ]; then # Fixup the commit message
# Handle options diff_msg
if [ -n "$1" ]; then
case "$1" in # Handle options
-h|--help) usage;; if [ -n "$1" ]; then
-n|--dry-run) cat "${FINAL_DIFF}";; case "$1" in
--commit) apply "${FINAL_DIFF}"; commit;; -h|--help) usage;;
--amend) apply "${FINAL_DIFF}"; amend;; -n|--dry-run) cat "${FINAL_DIFF}"; show_commit_msg_diff;;
*) usage;; --commit) apply "${FINAL_DIFF}"; commit;;
esac --amend) apply "${FINAL_DIFF}"; amend;;
else --msg-only) amend;;
apply "${FINAL_DIFF}" *) usage;;
if ! git diff --quiet; then esac
log "Formatting changes applied, verify and commit." else
log "See also: http://www.webmproject.org/code/contribute/conventions/" apply "${FINAL_DIFF}"
git diff --stat if ! git diff --quiet; then
fi log "Formatting changes applied, verify and commit."
log "See also: http://www.webmproject.org/code/contribute/conventions/"
git diff --stat
fi fi
fi fi
......
...@@ -182,7 +182,6 @@ def main(): ...@@ -182,7 +182,6 @@ def main():
if out_hunks: if out_hunks:
print FormatDiffHunks(out_hunks) print FormatDiffHunks(out_hunks)
else:
sys.exit(1) sys.exit(1)
if __name__ == "__main__": if __name__ == "__main__":
......
#!/usr/bin/env python
## Copyright (c) 2012 The WebM project authors. All Rights Reserved.
##
## Use of this source code is governed by a BSD-style license
## that can be found in the LICENSE file in the root of the source
## tree. An additional intellectual property rights grant can be found
## in the file PATENTS. All contributing project authors may
## be found in the AUTHORS file in the root of the source tree.
##
"""Wraps paragraphs of text, preserving manual formatting
This is like fold(1), but has the special convention of not modifying lines
that start with whitespace. This allows you to intersperse blocks with
special formatting, like code blocks, with written prose. The prose will
be wordwrapped, and the manual formatting will be preserved.
* This won't handle the case of a bulleted (or ordered) list specially, so
manual wrapping must be done.
Occasionally it's useful to put something with explicit formatting that
doesn't look at all like a block of text inline.
indicator = has_leading_whitespace(line);
if (indicator)
preserve_formatting(line);
The intent is that this docstring would make it through the transform
and still be legible and presented as it is in the source. If additional
cases are handled, update this doc to describe the effect.
"""
__author__ = "jkoleszar@google.com"
import textwrap
import sys
def wrap(text):
if text:
return textwrap.fill(text, break_long_words=False) + '\n'
return ""
def main(fileobj):
text = ""
output = ""
while True:
line = fileobj.readline()
if not line:
break
if line.lstrip() == line:
text += line
else:
output += wrap(text)
text=""
output += line
output += wrap(text)
# Replace the file or write to stdout.
if fileobj == sys.stdin:
fileobj = sys.stdout
else:
fileobj.truncate(0)
fileobj.write(output)
if __name__ == "__main__":
if len(sys.argv) > 1:
main(open(sys.argv[1], "r+"))
else:
main(sys.stdin)
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment