{"thread":{"id":"882","subject":"[PATCH 5/6] Make cg-diff use optparse, and add features","startedAt":"2005-06-09T11:24:07Z","lastAt":"2005-06-09T11:24:07Z","messageCount":1,"participants":["Dan Holmsand"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"4781","messageId":"42A826D7.1060507@gmail.com","threadId":"882","inReplyTo":null,"subject":"[PATCH 5/6] Make cg-diff use optparse, and add features","fromName":"Dan Holmsand","fromEmail":"holmsand@gmail.com","sentAt":"2005-06-09T11:24:07Z","receivedAt":"2005-06-09T11:24:07Z","isPatch":true,"sender":{"key":"holmsand@gmail.com","avatar":"https://gravatar.com/avatar/5c722084bafd85e754a02efad01fe69107eb6f393253c49232c5c9f7faa974df?d=mp&s=160"},"body":"This adds some new features to cg-diff:\n\n  - diffstat (or rather git-apply --stat) support. The\n    \"-d\" option outputs (optionally colorized) diff stats\n    before the diff.\n\n  - support for more git-diff-[tree/cache] options:\n    -B, -R, -M, -C are now all passed on.\n\n  - The COGITO_AUTO_COLOR environment variable makes output\n    automatically colorized, if set and if we're on a color\n    capable terminal.\n\nWe also use the new optparse function from cg-Xlib, to allow\nfor e.g. \"cg-diff -drorigin\" and stuff.\n\nReuse colorization logic from cg-Xlib.\n\nAnd use LESS to make \"less\" search for chunks and diff --git\nmarkers. This allows you to \"n\" your way through a series\nof diffs, and gives a nice visual separation of patches.\n\nSigned-off-by: Dan Holmsand <holmsand@gmail.com>\n---\n\n\n\n cg-diff |  222 +++++++++++++++++++++++++++++----------------------------------\n 1 files changed, 102 insertions(+), 120 deletions(-)\n\ndiff --git a/cg-diff b/cg-diff\n--- a/cg-diff\n+++ b/cg-diff\n@@ -5,13 +5,16 @@\n #\n # Outputs a diff for converting the first tree to the second one.\n # By default compares the current working tree to the state at the\n-# last commit. The output will automatically be displayed in a pager\n-# unless it is piped to a program.\n+# last commit.\n #\n # OPTIONS\n # -------\n-# -c::\n-#\tColorize the diff output\n+# -c, --color::\n+#\tColorize the diff output and use a pager for output (less by \n+#\tdefault).\n+#\n+# -d, --diffstat::\n+#\tShow `diffstat' before diff.\n #\n # -p::\n #\tInstead of one ID denotes a parent commit to the specified ID\n@@ -24,153 +27,132 @@\n #\tempty revision which means '-r rev:' compares between 'rev' and\n #\t'HEAD', while '-r rev' compares between 'rev' and working tree.\n #\n+# -R::\n+#\tOutput diff in reverse.\n+#\n+# -M::\n+#\tDetect renames.\n+#\n+# -C::\n+#\tDetect copies (as well as renames).\n+#\n+# -B::\n+#\tDetect rewrites.\n+#\n # -m::\n #\tBase the diff at the merge base of the -r arguments (defaulting\n-#\tto master and origin).\n+#\tto HEAD and origin).\n #\n # ENVIRONMENT VARIABLES\n # ---------------------\n # PAGER::\n #\tThe pager to display log information in, defaults to `less`.\n #\n-# PAGER_FLAGS::\n-#\tFlags to pass to the pager. By default `R` is added to the `LESS`\n-#\tenvironment variable to allow displaying of colorized output.\n+# COGITO_AUTO_COLOR::\n+#\tIf set, colorized output is used automatically on color-capable\n+#\tterminals.\n \n USAGE=\"cg-diff [-c] [-m] [-p] [-r FROM_ID[:TO_ID]] [FILE]...\"\n \n . ${COGITO_LIB}cg-Xlib\n \n \n-id1=\" \"\n-id2=\" \"\n-parent=\n-opt_color=\n-mergebase=\n-\n-# TODO: Make cg-log use this too.\n-setup_colors()\n-{\n-\tlocal C=\"diffhdr=1;36:diffhdradd=1;32:diffadd=32:diffhdrmod=1;35:diffmod=35:diffhdrrem=1;31:diffrem=31:diffhunk=36:diffctx=34:diffcctx=33:default=0\"\n-\t[ -n \"$COGITO_COLORS\" ] && C=\"$C:$COGITO_COLORS\"\n-\n-\tC=${C//=/=\\'$'\\e'[}\n-\tC=col${C//:/m\\'; col}m\\'\n-\t#coldefault=$(tput op)\n-\teval $C\n+unset id1 id2 parent diffprog sedprog diffstat difftmp opt_color renames\n+dtargs=()\n+\n+show_diffstat() {\n+\t[ -s \"$difftmp\" ] || return\n+\tgit-apply --stat \"$difftmp\"\n+\techo\n+\tcat \"$difftmp\"\n }\n \n-while [ \"$1\" ]; do\n-\tcase \"$1\" in\n-\t-c)\n-\t\topt_color=1\n-\t\tsetup_colors\n-\t\t;;\n-\t-p)\n+while optparse; do\n+\tif optparse -p; then\n \t\tparent=1\n-\t\t;;\n-\t-r)\n-\t\tshift\n-\t\tif echo \"$1\" | grep -q ':'; then\n-\t\t\tid2=$(echo \"$1\" | cut -d : -f 2)\n-\t\t\t[ \"$id2\" ] || log_end=\"HEAD\"\n-\t\t\tid1=$(echo \"$1\" | cut -d : -f 1)\n-\t\telif [ \"$id1\" = \" \" ]; then\n-\t\t\tid1=\"$1\"\n+\telif optparse -m; then\n+\t\tincoming=1\n+\telif optparse -r=; then\n+\t\tif [ -z \"${id1+set}\" ]; then\n+\t\t\tid1=$OPTARG\n+\t\t\tif [[ \"$id1\" == *:* ]]; then\n+\t\t\t\tid2=${id1#*:}\n+\t\t\t\tid1=${id1%:*}\n+\t\t\tfi\n \t\telse\n-\t\t\tid2=\"$1\"\n+\t\t\t[ -z \"${id2+set}\" ] || die \"too many revisions\"\n+\t\t\tid2=$OPTARG\n \t\tfi\n-\t\t;;\n-\t-m)\n-\t\tmergebase=1\n-\t\t;;\n-\t*)\n-\t\tbreak\n-\t\t;;\n-\tesac\n-\tshift\n-done\n-\n-colorize() {\n-\tif [ \"$opt_color\" ]; then\n-\t\tgawk '\n-\t\t{ if (/^(Index:|diff --git) /)\n-\t\t    print \"'$coldiffhdr'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^======*$/)\n-\t\t    print \"'$coldiffhdr'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^\\+\\+\\+/)\n-\t\t    print \"'$coldiffhdradd'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^\\*\\*\\*/)\n-\t\t    print \"'$coldiffhdrmod'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^---/)\n-\t\t    print \"'$coldiffhdrrem'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^(\\+|new( file)? mode )/)\n-\t\t    print \"'$coldiffadd'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^(-|(deleted file|old) mode )/)\n-\t\t    print \"'$coldiffrem'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^!/)\n-\t\t    print \"'$coldiffmod'\" $0 \"'$coldefault'\"\n-\t\t  else if (/^@@ \\-[0-9]+(,[0-9]+)? \\+[0-9]+(,[0-9]+)? @@/)\n-\t\t    print gensub(/^(@@[^@]*@@)([ \\t]*)(.*)/,\n-\t\t         \"'$coldiffhunk'\" \"\\\\1\" \"'$coldefault'\" \\\n-\t\t\t \"\\\\2\" \\\n-\t\t\t \"'$coldiffctx'\" \"\\\\3\" \"'$coldefault'\", \"\")\n-\t\t  else if (/^\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*\\*/)\n-\t\t    print \"'$coldiffcctx'\" $0 \"'$coldefault'\"\n-\t\t  else\n-\t\t    print\n-\t\t}'\n+\telif optparse -c; then\n+\t\topt_color=1\n+\telif optparse -d || optparse --diffstat; then\n+\t\tdiffstat=1\n+\telif optparse -R; then\n+\t\tdtargs[${#dtargs[@]}]=\"-R\"\n+\telif optparse -M; then\n+\t\t[ \"$renames\" ] && optconflict\n+\t\trenames=1\n+\t\tdtargs[${#dtargs[@]}]=\"-M\"\n+\telif optparse -C; then\n+\t\t[ \"$renames\" ] && optconflict\n+\t\trenames=1\n+\t\tdtargs[${#dtargs[@]}]=\"-C\"\n+\telif optparse -B; then\n+\t\tdtargs[${#dtargs[@]}]=\"-B\"\n \telse\n-\t\tcat\n+\t\toptfail\n \tfi\n-}\n+done\n \n-if [ \"$parent\" ]; then\n-\tid2=\"$id1\"\n-\tid=\"$id2\"; [ \"$id\" = \" \" ] && id=\"\"\n-\tid1=$(parent-id \"$id\" | head -n 1) || exit 1\n-fi\n+[ -n \"$COGITO_AUTO_COLOR\" -a -t 1 ] && [ \"$(tput setaf 1 2>/dev/null)\" ] && \n+opt_color=1\n \n-if [ \"$mergebase\" ]; then\n-\t[ \"$id1\" != \" \" ] || id1=\"master\"\n-\t[ \"$id2\" != \" \" ] || id2=\"origin\"\n-\tid1=$(git-merge-base $(commit-id \"$id1\") $(commit-id \"$id2\"))\n-fi\n+LESS=$'+/\\013^@@.*@@|^diff.--git..*$'\" $LESS\"\n \n+diffprog=git-diff-tree\n \n-filter=$(mktemp -t gitdiff.XXXXXX)\n-for file in \"$@\"; do\n-\techo \"$file\" >>$filter\n-done\n+if [ \"$parent\" ]; then\n+\t[ -z \"${id2+set}\" ] || die \"too many revisions\"\n+\tid2=\"$id1\"\n+\tid1=$(parent-id \"$id2\" | head -n 1) || exit 1\n+elif [ \"$incoming\" ]; then\n+\ttmp=$id1\n+\tid1=\"$(commit-id \"${id2:-HEAD}\")\" || exit 1\n+\tid2=\"$(commit-id \"${tmp:-origin}\")\" || exit 1\n+\tid1=\"$(git-merge-base \"$id1\" \"$id2\")\" || exit 1\n+fi\n \n-if [ \"$id2\" = \" \" ]; then\n-\tif [ \"$id1\" != \" \" ]; then\n-\t\ttree=$(tree-id \"$id1\") || exit 1\n-\telse\n-\t\ttree=$(tree-id) || exit 1\n-\tfi\n+id1=$(tree-id \"$id1\") || exit 1\n \n+if [ -z \"${id2+set}\" ]; then\n \t# Ensure to only diff modified files\n \tgit-update-cache --refresh >/dev/null\n-\n-\t# FIXME: Update ret based on what did we match. And take \"$@\"\n-\t# to account after all.\n-\tret=\n-\tcat $filter | xargs git-diff-cache -r -p $tree | colorize | pager\n-\n-\trm $filter\n-\n-\t[ \"$ret\" ] && die \"no files matched\"\n-\texit $ret\n+\tdiffprog=git-diff-cache\n+else\n+\tid2=$(tree-id \"$id2\") || exit 1\n fi\n \n-\n-id1=$(tree-id \"$id1\") || exit 1\n-id2=$(tree-id \"$id2\") || exit 1\n-\n [ \"$id1\" = \"$id2\" ] && die \"trying to diff $id1 against itself\"\n+diffopts=(-r -p \"${dtargs[@]}\" $id1 $id2 \"${ARGS[@]}\")\n+\n+if [ \"$diffstat\" ]; then\n+\tdifftmp=$(mktemp -t cgdiff.XXXXXX) || exit 1\n+\ttrap \"rm '$difftmp'\" SIGTERM EXIT\n+\t$diffprog \"${diffopts[@]}\" > $difftmp\n \n-cat $filter | xargs git-diff-tree -r -p $id1 $id2 | colorize | pager\n+\tdiffprog=show_diffstat\n+\tdiffopts=\n+fi\n \n-rm $filter\n-exit 0\n+if [ \"$opt_color\" ]; then\n+\tsetup_colors\n+\tsedprog=\"$color_rules\"\n+\n+\t[ \"$diffstat\" ] && sedprog=\"$sedprog\n+s,^\\\\( [^ ].*\\\\)\\\\( |  *[0-9][0-9]* \\\\),$colfiles\\\\1$coldefault\\\\2,\"\n+\n+\t$diffprog \"${diffopts[@]}\" | sed -e \"$sedprog\" | pager\n+\texit $PIPESTATUS\n+else\n+\t$diffprog \"${diffopts[@]}\"\n+fi\n"}]}