[PATCH 01/15] git-note: Add git-note command for adding/listing/deleting git notes

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Synopsis:
'git-note' [-m <msg> | -F <file>] [<head>]
'git-note' -l [<name>...]
'git-note' -d <name>...

'git-note' without any parameters creates 'note' associated with HEAD.
Specifying an object name/ref to 'git-note' will cause the note to
be associated with that object instead.

`git-note -l [<name>...]` lists notes associated with the given <name>s.
If no <name> is given, all notes are listed. The given <name> may itself
be a note object, in which case it is listed along with its associated
notes (if any).

`git-note -d <name>...` deletes the notes associated with the given
<name>s. The given <name> may itself be a note object, in which case it is
deleted along with its associated notes (if any).

git-note.sh is partly based on git-tag.sh

Signed-off-by: Johan Herland <johan@xxxxxxxxxxx>
---
 git-note.sh |  227 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 227 insertions(+), 0 deletions(-)
 create mode 100755 git-note.sh

diff --git a/git-note.sh b/git-note.sh
new file mode 100755
index 0000000..4f539e2
--- /dev/null
+++ b/git-note.sh
@@ -0,0 +1,227 @@
+#!/bin/sh
+
+USAGE='-l [<name>...] | -d <name>... | [-m <msg> | -F <file>] [<head>]'
+LONG_USAGE='Add, delete and show git object notes
+	-l	list/show notes associated with the given object.
+	-d	delete the notes associated with the given object.
+	-m	use the given note message (instead of prompting).
+	-F 	Take the note message from the given file (instead of prompting).
+For -l and -d, the given <name> may be a note object itself, in which case
+it will be included in the listing/deletion.
+When <head> is not given, it defaults to HEAD.'
+SUBDIRECTORY_OK='Yes'
+. git-sh-setup
+
+
+# Show the note identified by $1
+show_note () {
+	authordate=$(git-cat-file -p $1 | grep -m1 '^tagger ' | cut -c8-)
+	echo
+	echo "--- by $authordate"
+	git-cat-file -p $1 | tail -n+6
+	return 0
+}
+
+# Show notes below the refs/notes directory given in $1
+show_notes_below_dir () {
+	prev_object=
+	for note_data in $(git-for-each-ref --shell \
+			--sort=-taggerdate --sort=*authordate \
+			--format='note=%(objectname);object=%(*objectname);object_type=%(*objecttype);object_tag=%(*tag);' \
+			$1)
+	do
+		eval "$note_data"
+
+		# Separate note objects from regular tags
+		if test "$object_type" = "tag" -a -n "$(echo "$object_tag" | grep '^note-')"; then
+			object_type="note"
+			object_tag=""
+		fi
+
+		description=
+		# Create description based on object type
+		case "$object_type" in
+		commit)
+			description="$(git-show --pretty='format:%h (%s) by %an <%ae> on %aD' $object | head -n1)"
+			;;
+		tag)
+			description="$object ($object_tag)"
+			;;
+		*)
+			description="$object"
+			;;
+		esac
+
+		if test "$object" != "$prev_object"; then
+			test -z "$prev_object" || echo
+			echo "=== Notes on $object_type $description"
+		fi
+		show_note $note
+		prev_object="$object"
+	done
+	return 0
+}
+
+# Show the notes associated with the objects in $@
+show_associated_notes () {
+	if test "$#" = "0"; then
+		show_notes_below_dir "refs/notes"
+		return 0
+	fi
+
+	while case "$#" in 0) break ;; esac
+	do
+		obj=$(git-rev-parse --verify "$1") || \
+				die "error: failed to find object named '$1'"
+
+		# If $obj is a note itself, handle it first
+		if test "$(git-cat-file -t $obj)" = "tag"; then
+			if test -n "$(git-cat-file -p $obj | grep '^tag note-')"; then
+				echo
+				echo "=== Note $obj"
+				show_note "$obj"
+			fi
+		fi
+
+		# List all notes associated with $obj.
+		show_notes_below_dir "refs/notes/$obj"
+
+		shift
+	done
+	return 0
+}
+
+# Delete the noteref in $1 pointing to the note identified by the SHA1 in $2
+delete_note () {
+	git-update-ref -m "note: delete" -d "$1" "$2"
+	return 0
+}
+
+# Delete all notes associated with object in $1
+delete_object_notes () {
+	for note_data in $(git-for-each-ref --shell \
+			--sort=taggerdate --sort=*authordate \
+			--format='note=%(objectname);object=%(*objectname);object_type=%(*objecttype);noteref=%(refname)' \
+			refs/notes/$1)
+	do
+		eval "$note_data"
+		echo "Deleting note $note associated with $object_type $object"
+		delete_note "$noteref" "$note"
+	done
+
+	# Try to get rid of $object's directory below refs/notes as well
+	if test -d "$GIT_DIR/refs/notes/$1"; then
+		rmdir "$GIT_DIR/refs/notes/$1"
+	fi
+	return 0
+}
+
+# Delete the notes associated with the objects in $@
+delete_associated_notes () {
+	while case "$#" in 0) break ;; esac
+	do
+		obj=$(git-rev-parse --verify "$1") || \
+				die "error: failed to find object named '$1'"
+
+		# If $obj is a note itself, handle it first
+		if test "$(git-cat-file -t $obj)" = "tag"; then
+			objref="$(git-cat-file -p $obj | grep -m1 '^object ' | cut -c8-)"
+			if test -n "$objref"; then
+				echo "Deleting note $obj"
+				delete_note "refs/notes/$objref/$obj" "$obj"
+			fi
+		fi
+
+		# Delete all notes associated with $obj
+		delete_object_notes "$obj"
+
+		shift
+	done
+	return 0
+}
+
+message_given=
+message=
+while case "$#" in 0) break ;; esac
+do
+	case "$1" in
+	-l)
+		shift
+		show_associated_notes "$@"
+		exit $?
+		;;
+	-d)
+		shift
+		if test "$#" = "0"; then
+			die "error: option -d needs one or more objects"
+		fi
+		delete_associated_notes "$@"
+		exit $?
+		;;
+	-m)
+		shift
+		message="$1"
+		if test "$#" = "0"; then
+			die "error: option -m needs an argument"
+		else
+			message_given=1
+		fi
+		;;
+	-F)
+		shift
+		if test "$#" = "0"; then
+			die "error: option -F needs an argument"
+		else
+			message="$(cat "$1")"
+			message_given=1
+		fi
+		;;
+	-*)
+		usage
+		;;
+	*)
+		break
+		;;
+	esac
+	shift
+done
+
+object=$(git-rev-parse --verify --default HEAD "$@") || exit 1
+type=$(git-cat-file -t $object) || exit 1
+tagger=$(git-var GIT_COMMITTER_IDENT) || exit 1
+
+# Process note message
+trap 'rm -f "$GIT_DIR"/NOTE_TMP* "$GIT_DIR"/NOTE_FINALMSG "$GIT_DIR"/NOTE_EDITMSG' 0
+
+if test -z "$message_given"; then
+	( echo ""
+	  echo "#"
+	  echo "# Write a note on $type $object"
+	  echo "#" ) > "$GIT_DIR/NOTE_EDITMSG"
+	${VISUAL:-${EDITOR:-vi}} "$GIT_DIR/NOTE_EDITMSG" || exit
+else
+	printf '%s\n' "$message" >"$GIT_DIR/NOTE_EDITMSG"
+fi
+
+grep -v '^#' <"$GIT_DIR/NOTE_EDITMSG" |
+git-stripspace >"$GIT_DIR/NOTE_FINALMSG"
+
+test -s "$GIT_DIR/NOTE_FINALMSG" -o -n "$message_given" || {
+	echo >&2 "No note?"
+	exit 1
+}
+
+name="note-`( printf 'object %s\ntagger %s\n\n' "$tagger"; \
+              cat "$GIT_DIR/NOTE_FINALMSG" ) \
+            | sha1sum | cut -d" " -f1`"
+
+git-check-ref-format "notes/$object/$name" ||
+	die "Failed to create a valid note name. (internal git-note error)"
+
+( printf 'object %s\ntype %s\ntag %s\ntagger %s\n\n' \
+		"$object"  "$type"  "$name" "$tagger";
+		cat "$GIT_DIR/NOTE_FINALMSG" ) >"$GIT_DIR/NOTE_TMP"
+rm -f "$GIT_DIR/NOTE_FINALMSG"
+note=$(git-mktag < "$GIT_DIR/NOTE_TMP")
+
+git-update-ref "refs/notes/$object/$note" "$note"
-- 
1.5.2.101.gee49f


-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux