8

When I do svn commit and let my svn editor pick it up I'd LOVE for the svn editor to show the diff of the files that have changed instead of just the list of files. Really helps jog the memory when writing detailed commit messages. Any ideas on how to accomplish?

dstarh
  • 4,976
  • 5
  • 36
  • 68
  • With TortoiseSVN (and many others) you can double-click on any file in that list to see a diff. You can also select multiple and right-click diff. – JoshD Oct 07 '10 at 18:57
  • 2
    i'm talking command line on a terminal where i've set the SVN_EDITOR property and I either point that to vim or textmate which do automatic syntax highlighting for either the commit or diff depending on which i pipe to it. – dstarh Oct 07 '10 at 19:08
  • @Josh i can easily svn diff | mate and see the diff of anything that changed but when i type svn commit and mate or vim loads it currently just shows a list of files via svn status, i'd really like below that to see the output of svn diff – dstarh Oct 07 '10 at 19:10

4 Answers4

7

Looks like the script here works after all.

From - http://push.cx/2007/seeing-subversion-diffs-for-commit-messages

Needed to make a few changes. I'll paste the entire script here

create a file, name it svn in this case it's put in ~/bin

#!/bin/sh
REALSVN=/usr/bin/svn

ARGS="$@"

if [ "$1" = "commit" -o "$1" = "ci" ]; then
    shift # pop off $1 for diff
    TEMPLATE=`mktemp -t tmp`
    $REALSVN diff "$@" > "$TEMPLATE"
    $REALSVN $ARGS --editor-cmd="~/bin/svn-diff-editor '$TEMPLATE'"
else
    $REALSVN $ARGS
fi

and also create a file named ~/bin/svn-diff-editor

echo >> "$2"
cat "$1" >> "$2"
rm "$1"
$SVN_EDITOR "$2"

for osx i had to add the '-t tmp' to mktmp and the orig script had $VISUAL which I did not have and had $SVN_EDITOR set instead, once I changed the last line of svn-diff-editor to that it worked.

dstarh
  • 4,976
  • 5
  • 36
  • 68
  • I should note that both files need to be chmod+x'd and ~/bin should be first in your path... or just put this anywhere that's ahead of the real svn in your path – dstarh Oct 07 '10 at 20:27
1

Write a script

It would take some work, but you could write a script to front end as your SVN_EDITOR. When svn invokes your SVN_EDITOR, it passes the name of an svn-generated temporary comment file containing the summary list of affected files to be committed.

http://svnbook.red-bean.com/en/1.5/svn-book.html#svn.advanced.externaleditors

The value of any of these options or variables is the beginning of a command line to be executed by the shell. Subversion appends to that command line a space and the pathname of a temporary file to be edited. So, to be used with Subversion, the configured or specified editor needs to support an invocation in which its last command-line parameter is a file to be edited, and it should be able to save the file in place and return a zero exit code to indicate success.

Conceivably, you could write a shell script that takes a filename parameter that:

  1. opens the file indicated by the last arg (the svn temporary comment file)
  2. parses it for the files to be committed
  3. runs svn diff on each modified (non-binary) file and appends the diff output back to the end of the svn temporary comment file
  4. invokes your real editor on the modified svn temporary comment file

Make sure your script returns the return code returned by your real editor or 0 to indicate success. Then set your SVN_EDITOR env var to point to your script.

Perhaps someone has already written such a script, but I couldn't find one (especially since you didn't indicate an OS). There's also a good chance that this script could generate an extremely large file.

Alternative - write a macro

I think a better alternative would be to use a programmable editor and program a macro that read a filename(s) from some selected line(s) and then run SVN diff on the file(s) - putting the results in a buffer or appending it to current buffer . You could then selectively highlight files from the svn temporary comment file and run SVN diff on just the key files you need. Sounds like a job for elisp!

Sorry I don't have an ready-made code for you. If you do either of these, it would be interesting to see come back and post your script/macro back here as an answer.

Bert F
  • 85,407
  • 12
  • 106
  • 123
  • Just found http://push.cx/2007/seeing-subversion-diffs-for-commit-messages but it's not seeming to work on osx – dstarh Oct 07 '10 at 20:02
  • 1
    I bow to your superior searching skills. – Bert F Oct 07 '10 at 20:06
  • I'm accepting this answer because it's essentially what I did :) – dstarh Oct 07 '10 at 20:34
  • @dstarh - I would be fine if you accepted yours - its a complete solution and it should appear as the first answer for the sake of future programmers searching for a similar solution. – Bert F Oct 07 '10 at 21:28
  • Wont let me yet. Will do later. Really loving this. Especially since I told textmate it's diff content and get the lovely highlighting – dstarh Oct 08 '10 at 00:28
0

I couldn't find an answer that I felt like using. dstarh's answer is almost there. But it's too intrusive to me. What if there are arguments before commit? Additionally, it's safer to delete the temporary file with a trap. And to please the paranoid folk, I escape the editor cmd:

svn-commit.sh:

#!/usr/bin/env bash
set -eu
tmp=`mktemp` _trap="rm -r "$tmp"; ${_trap:-}" && trap "$_trap" EXIT
svn diff "$@" > "$tmp"
# svn diff "$@" | iconv -f utf-8 -t utf-8 -c > "$tmp"   # skip malformed UTF-8 characters
svn commit "$@" "--editor-cmd=svn-editor.sh $(printf %q "$tmp")"

svn-editor.sh:

#!/usr/bin/env bash
set -eu
diff_f=$1
commit_msg_f=$2
# dos2unix "$diff_f"   # if svn repo has files with different line-ending styles
# dos2unix -f "$diff_f"   # to make it always treat diff output as text
echo >> "$commit_msg_f"

cat "$diff_f" >> "$commit_msg_f"
"$EDITOR" "$commit_msg_f"

UPD I've run into this error:

svn: E135000: Commit failed (details follow):
svn: E135000: Error normalizing edited contents to internal format
svn: E135000: Inconsistent line ending style
svn: E135000: Your commit message was left in a temporary file:
svn: E135000:    '.../svn-commit.tmp'

One could consider adding dos2unix command or something as done in the comment.

UPD Additionally, you may want to skip malformed UTF-8 characters, or else svn will fail:

svn: E000022: Commit failed (details follow):
svn: E000022: Error normalizing edited contents to internal format
svn: E000022: Valid UTF-8 data
(hex: 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 2f 0a 2b 0a 2b)
followed by invalid UTF-8 sequence
(hex: a4 20 3d 20)
svn: E000022: Your commit message was left in a temporary file:
svn: E000022:    '.../svn-commit.tmp'

UPD And occasionally dos2unix might treat diff output as binary:

dos2unix: Binary symbol 0x00 found at line 742308
dos2unix: Skipping binary file /tmp/tmp.UCNcubZZlX
svn: E135000: Commit failed (details follow):
svn: E135000: Error normalizing edited contents to internal format
svn: E135000: Inconsistent line ending style
svn: E135000: Your commit message was left in a temporary file:
svn: E135000:    '.../svn-commit.tmp'

You may want to force conversion.

Community
  • 1
  • 1
x-yuri
  • 16,722
  • 15
  • 114
  • 161
0

I wrote a simple script and set SVN_EDITOR to its path:

#!/bin/bash

tmpFile="${!#}"

# Append changes in committed files to tmpFile
echo >> ${tmpFile}
grep '^[MR]' ${tmpFile} | awk '{print $2}' | \
  xargs -n 1 --no-run-if-empty svn diff >> ${tmpFile}

# Run editor
exec ${EDITOR} ${tmpFile}

Note that it only looks for modified (M) and replaced (R) files and assumes EDITOR is set. Should probably not try to diff binary files.

sappjw
  • 373
  • 1
  • 14
  • interesting solution. I really like the diff output that SVN has by default which is what I wanted - the usual commit output just lists the files and the status, but svn diff will give you proper diff layout without having to call svn diff on each file separately. – dstarh Feb 09 '11 at 21:09