From: Junio C Hamano Date: Mon, 15 Mar 2010 07:52:06 +0000 (-0700) Subject: Merge branch 'jh/notes' X-Git-Tag: v1.7.1-rc0~68 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/2949151fe9d92b2c3405f188e650d9bb7b46c663?ds=inline;hp=-c Merge branch 'jh/notes' * jh/notes: (33 commits) Documentation: fix a few typos in git-notes.txt notes: fix malformed tree entry builtin-notes: Minor (mostly parse_options-related) fixes builtin-notes: Add "copy" subcommand for copying notes between objects builtin-notes: Misc. refactoring of argc and exit value handling builtin-notes: Add -c/-C options for reusing notes builtin-notes: Refactor handling of -F option to allow combining -m and -F builtin-notes: Deprecate the -m/-F options for "git notes edit" builtin-notes: Add "append" subcommand for appending to note objects builtin-notes: Add "add" subcommand for adding notes to objects builtin-notes: Add --message/--file aliases for -m/-F options builtin-notes: Add "list" subcommand for listing note objects Documentation: Generalize git-notes docs to 'objects' instead of 'commits' builtin-notes: Add "prune" subcommand for removing notes for missing objects Notes API: prune_notes(): Prune notes that belong to non-existing objects t3305: Verify that removing notes triggers automatic fanout consolidation builtin-notes: Add "remove" subcommand for removing existing notes Teach builtin-notes to remove empty notes Teach notes code to properly preserve non-notes in the notes tree t3305: Verify that adding many notes with git-notes triggers increased fanout ... Conflicts: Makefile --- 2949151fe9d92b2c3405f188e650d9bb7b46c663 diff --combined Makefile index 8fdc421073,1f95f93f76..7c616f8b0a --- a/Makefile +++ b/Makefile @@@ -180,6 -180,9 +180,6 @@@ all: # If not set it defaults to the bare 'wish'. If it is set to the empty # string then NO_TCLTK will be forced (this is used by configure script). # -# Define THREADED_DELTA_SEARCH if you have pthreads and wish to exploit -# parallel delta searching when packing objects. -# # Define INTERNAL_QSORT to use Git's implementation of qsort(), which # is a simplified version of the merge sort used in glibc. This is # recommended if Git triggers O(n^2) behavior in your platform's qsort(). @@@ -214,13 -217,6 +214,13 @@@ # DEFAULT_EDITOR='~/bin/vi', # DEFAULT_EDITOR='$GIT_FALLBACK_EDITOR', # DEFAULT_EDITOR='"C:\Program Files\Vim\gvim.exe" --nofork' +# +# Define COMPUTE_HEADER_DEPENDENCIES if your compiler supports the -MMD option +# and you want to avoid rebuilding objects when an unrelated header file +# changes. +# +# Define CHECK_HEADER_DEPENDENCIES to check for problems in the hard-coded +# dependency rules. GIT-VERSION-FILE: FORCE @$(SHELL_PATH) ./GIT-VERSION-GEN @@@ -282,6 -278,29 +282,6 @@@ pathsep = # JavaScript minifier invocation that can function as filter JSMIN = -# default configuration for gitweb -GITWEB_CONFIG = gitweb_config.perl -GITWEB_CONFIG_SYSTEM = /etc/gitweb.conf -GITWEB_HOME_LINK_STR = projects -GITWEB_SITENAME = -GITWEB_PROJECTROOT = /pub/git -GITWEB_PROJECT_MAXDEPTH = 2007 -GITWEB_EXPORT_OK = -GITWEB_STRICT_EXPORT = -GITWEB_BASE_URL = -GITWEB_LIST = -GITWEB_HOMETEXT = indextext.html -GITWEB_CSS = gitweb.css -GITWEB_LOGO = git-logo.png -GITWEB_FAVICON = git-favicon.png -ifdef JSMIN -GITWEB_JS = gitweb.min.js -else -GITWEB_JS = gitweb.js -endif -GITWEB_SITE_HEADER = -GITWEB_SITE_FOOTER = - export prefix bindir sharedir sysconfdir CC = gcc @@@ -308,7 -327,7 +308,7 @@@ SPARSE_FLAGS = -D__BIG_ENDIAN__ -D__pow # Those must not be GNU-specific; they are shared with perl/ which may # be built by a different compiler. (Note that this is an artifact now # but it still might be nice to keep that distinction.) -BASIC_CFLAGS = +BASIC_CFLAGS = -I. BASIC_LDFLAGS = # Guard against environment variables @@@ -318,13 -337,11 +318,13 @@@ COMPAT_CFLAGS COMPAT_OBJS = LIB_H = LIB_OBJS = +PROGRAM_OBJS = PROGRAMS = SCRIPT_PERL = SCRIPT_PYTHON = SCRIPT_SH = -TEST_PROGRAMS = +SCRIPT_LIB = +TEST_PROGRAMS_NEED_X = SCRIPT_SH += git-am.sh SCRIPT_SH += git-bisect.sh @@@ -335,21 -352,19 +335,20 @@@ SCRIPT_SH += git-merge-octopus.s SCRIPT_SH += git-merge-one-file.sh SCRIPT_SH += git-merge-resolve.sh SCRIPT_SH += git-mergetool.sh - SCRIPT_SH += git-notes.sh -SCRIPT_SH += git-mergetool--lib.sh -SCRIPT_SH += git-parse-remote.sh SCRIPT_SH += git-pull.sh SCRIPT_SH += git-quiltimport.sh SCRIPT_SH += git-rebase--interactive.sh SCRIPT_SH += git-rebase.sh SCRIPT_SH += git-repack.sh SCRIPT_SH += git-request-pull.sh -SCRIPT_SH += git-sh-setup.sh SCRIPT_SH += git-stash.sh SCRIPT_SH += git-submodule.sh SCRIPT_SH += git-web--browse.sh +SCRIPT_LIB += git-mergetool--lib +SCRIPT_LIB += git-parse-remote +SCRIPT_LIB += git-sh-setup + SCRIPT_PERL += git-add--interactive.perl SCRIPT_PERL += git-difftool.perl SCRIPT_PERL += git-archimport.perl @@@ -370,35 -385,16 +369,35 @@@ EXTRA_PROGRAMS # ... and all the rest that could be moved out of bindir to gitexecdir PROGRAMS += $(EXTRA_PROGRAMS) -PROGRAMS += git-fast-import$X -PROGRAMS += git-imap-send$X -PROGRAMS += git-shell$X -PROGRAMS += git-show-index$X -PROGRAMS += git-upload-pack$X -PROGRAMS += git-http-backend$X + +PROGRAM_OBJS += fast-import.o +PROGRAM_OBJS += imap-send.o +PROGRAM_OBJS += shell.o +PROGRAM_OBJS += show-index.o +PROGRAM_OBJS += upload-pack.o +PROGRAM_OBJS += http-backend.o + +PROGRAMS += $(patsubst %.o,git-%$X,$(PROGRAM_OBJS)) + +TEST_PROGRAMS_NEED_X += test-chmtime +TEST_PROGRAMS_NEED_X += test-ctype +TEST_PROGRAMS_NEED_X += test-date +TEST_PROGRAMS_NEED_X += test-delta +TEST_PROGRAMS_NEED_X += test-dump-cache-tree +TEST_PROGRAMS_NEED_X += test-genrandom +TEST_PROGRAMS_NEED_X += test-match-trees +TEST_PROGRAMS_NEED_X += test-parse-options +TEST_PROGRAMS_NEED_X += test-path-utils +TEST_PROGRAMS_NEED_X += test-run-command +TEST_PROGRAMS_NEED_X += test-sha1 +TEST_PROGRAMS_NEED_X += test-sigchain +TEST_PROGRAMS_NEED_X += test-index-version + +TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X)) # List built-in command $C whose implementation cmd_$C() is not in -# builtin-$C.o but is linked in as part of some other command. -BUILT_INS += $(patsubst builtin-%.o,git-%$X,$(BUILTIN_OBJS)) +# builtin/$C.o but is linked in as part of some other command. +BUILT_INS += $(patsubst builtin/%.o,git-%$X,$(BUILTIN_OBJS)) BUILT_INS += git-cherry$X BUILT_INS += git-cherry-pick$X @@@ -454,7 -450,6 +453,7 @@@ LIB_H += blob. LIB_H += builtin.h LIB_H += cache.h LIB_H += cache-tree.h +LIB_H += color.h LIB_H += commit.h LIB_H += compat/bswap.h LIB_H += compat/cygwin.h @@@ -466,7 -461,6 +465,7 @@@ LIB_H += delta. LIB_H += diffcore.h LIB_H += diff.h LIB_H += dir.h +LIB_H += exec_cmd.h LIB_H += fsck.h LIB_H += git-compat-util.h LIB_H += graph.h @@@ -509,8 -503,7 +508,8 @@@ LIB_H += tree-walk. LIB_H += unpack-trees.h LIB_H += userdiff.h LIB_H += utf8.h -LIB_H += wt-status.h +LIB_H += xdiff-interface.h +LIB_H += xdiff/xdiff.h LIB_OBJS += abspath.o LIB_OBJS += advice.o @@@ -624,95 -617,96 +623,96 @@@ LIB_OBJS += ws. LIB_OBJS += wt-status.o LIB_OBJS += xdiff-interface.o -BUILTIN_OBJS += builtin-add.o -BUILTIN_OBJS += builtin-annotate.o -BUILTIN_OBJS += builtin-apply.o -BUILTIN_OBJS += builtin-archive.o -BUILTIN_OBJS += builtin-bisect--helper.o -BUILTIN_OBJS += builtin-blame.o -BUILTIN_OBJS += builtin-branch.o -BUILTIN_OBJS += builtin-bundle.o -BUILTIN_OBJS += builtin-cat-file.o -BUILTIN_OBJS += builtin-check-attr.o -BUILTIN_OBJS += builtin-check-ref-format.o -BUILTIN_OBJS += builtin-checkout-index.o -BUILTIN_OBJS += builtin-checkout.o -BUILTIN_OBJS += builtin-clean.o -BUILTIN_OBJS += builtin-clone.o -BUILTIN_OBJS += builtin-commit-tree.o -BUILTIN_OBJS += builtin-commit.o -BUILTIN_OBJS += builtin-config.o -BUILTIN_OBJS += builtin-count-objects.o -BUILTIN_OBJS += builtin-describe.o -BUILTIN_OBJS += builtin-diff-files.o -BUILTIN_OBJS += builtin-diff-index.o -BUILTIN_OBJS += builtin-diff-tree.o -BUILTIN_OBJS += builtin-diff.o -BUILTIN_OBJS += builtin-fast-export.o -BUILTIN_OBJS += builtin-fetch-pack.o -BUILTIN_OBJS += builtin-fetch.o -BUILTIN_OBJS += builtin-fmt-merge-msg.o -BUILTIN_OBJS += builtin-for-each-ref.o -BUILTIN_OBJS += builtin-fsck.o -BUILTIN_OBJS += builtin-gc.o -BUILTIN_OBJS += builtin-grep.o -BUILTIN_OBJS += builtin-hash-object.o -BUILTIN_OBJS += builtin-help.o -BUILTIN_OBJS += builtin-index-pack.o -BUILTIN_OBJS += builtin-init-db.o -BUILTIN_OBJS += builtin-log.o -BUILTIN_OBJS += builtin-ls-files.o -BUILTIN_OBJS += builtin-ls-remote.o -BUILTIN_OBJS += builtin-ls-tree.o -BUILTIN_OBJS += builtin-mailinfo.o -BUILTIN_OBJS += builtin-mailsplit.o -BUILTIN_OBJS += builtin-merge.o -BUILTIN_OBJS += builtin-merge-base.o -BUILTIN_OBJS += builtin-merge-file.o -BUILTIN_OBJS += builtin-merge-index.o -BUILTIN_OBJS += builtin-merge-ours.o -BUILTIN_OBJS += builtin-merge-recursive.o -BUILTIN_OBJS += builtin-merge-tree.o -BUILTIN_OBJS += builtin-mktag.o -BUILTIN_OBJS += builtin-mktree.o -BUILTIN_OBJS += builtin-mv.o -BUILTIN_OBJS += builtin-name-rev.o -BUILTIN_OBJS += builtin-notes.o -BUILTIN_OBJS += builtin-pack-objects.o -BUILTIN_OBJS += builtin-pack-redundant.o -BUILTIN_OBJS += builtin-pack-refs.o -BUILTIN_OBJS += builtin-patch-id.o -BUILTIN_OBJS += builtin-prune-packed.o -BUILTIN_OBJS += builtin-prune.o -BUILTIN_OBJS += builtin-push.o -BUILTIN_OBJS += builtin-read-tree.o -BUILTIN_OBJS += builtin-receive-pack.o -BUILTIN_OBJS += builtin-reflog.o -BUILTIN_OBJS += builtin-remote.o -BUILTIN_OBJS += builtin-replace.o -BUILTIN_OBJS += builtin-rerere.o -BUILTIN_OBJS += builtin-reset.o -BUILTIN_OBJS += builtin-rev-list.o -BUILTIN_OBJS += builtin-rev-parse.o -BUILTIN_OBJS += builtin-revert.o -BUILTIN_OBJS += builtin-rm.o -BUILTIN_OBJS += builtin-send-pack.o -BUILTIN_OBJS += builtin-shortlog.o -BUILTIN_OBJS += builtin-show-branch.o -BUILTIN_OBJS += builtin-show-ref.o -BUILTIN_OBJS += builtin-stripspace.o -BUILTIN_OBJS += builtin-symbolic-ref.o -BUILTIN_OBJS += builtin-tag.o -BUILTIN_OBJS += builtin-tar-tree.o -BUILTIN_OBJS += builtin-unpack-file.o -BUILTIN_OBJS += builtin-unpack-objects.o -BUILTIN_OBJS += builtin-update-index.o -BUILTIN_OBJS += builtin-update-ref.o -BUILTIN_OBJS += builtin-update-server-info.o -BUILTIN_OBJS += builtin-upload-archive.o -BUILTIN_OBJS += builtin-var.o -BUILTIN_OBJS += builtin-verify-pack.o -BUILTIN_OBJS += builtin-verify-tag.o -BUILTIN_OBJS += builtin-write-tree.o +BUILTIN_OBJS += builtin/add.o +BUILTIN_OBJS += builtin/annotate.o +BUILTIN_OBJS += builtin/apply.o +BUILTIN_OBJS += builtin/archive.o +BUILTIN_OBJS += builtin/bisect--helper.o +BUILTIN_OBJS += builtin/blame.o +BUILTIN_OBJS += builtin/branch.o +BUILTIN_OBJS += builtin/bundle.o +BUILTIN_OBJS += builtin/cat-file.o +BUILTIN_OBJS += builtin/check-attr.o +BUILTIN_OBJS += builtin/check-ref-format.o +BUILTIN_OBJS += builtin/checkout-index.o +BUILTIN_OBJS += builtin/checkout.o +BUILTIN_OBJS += builtin/clean.o +BUILTIN_OBJS += builtin/clone.o +BUILTIN_OBJS += builtin/commit-tree.o +BUILTIN_OBJS += builtin/commit.o +BUILTIN_OBJS += builtin/config.o +BUILTIN_OBJS += builtin/count-objects.o +BUILTIN_OBJS += builtin/describe.o +BUILTIN_OBJS += builtin/diff-files.o +BUILTIN_OBJS += builtin/diff-index.o +BUILTIN_OBJS += builtin/diff-tree.o +BUILTIN_OBJS += builtin/diff.o +BUILTIN_OBJS += builtin/fast-export.o +BUILTIN_OBJS += builtin/fetch-pack.o +BUILTIN_OBJS += builtin/fetch.o +BUILTIN_OBJS += builtin/fmt-merge-msg.o +BUILTIN_OBJS += builtin/for-each-ref.o +BUILTIN_OBJS += builtin/fsck.o +BUILTIN_OBJS += builtin/gc.o +BUILTIN_OBJS += builtin/grep.o +BUILTIN_OBJS += builtin/hash-object.o +BUILTIN_OBJS += builtin/help.o +BUILTIN_OBJS += builtin/index-pack.o +BUILTIN_OBJS += builtin/init-db.o +BUILTIN_OBJS += builtin/log.o +BUILTIN_OBJS += builtin/ls-files.o +BUILTIN_OBJS += builtin/ls-remote.o +BUILTIN_OBJS += builtin/ls-tree.o +BUILTIN_OBJS += builtin/mailinfo.o +BUILTIN_OBJS += builtin/mailsplit.o +BUILTIN_OBJS += builtin/merge.o +BUILTIN_OBJS += builtin/merge-base.o +BUILTIN_OBJS += builtin/merge-file.o +BUILTIN_OBJS += builtin/merge-index.o +BUILTIN_OBJS += builtin/merge-ours.o +BUILTIN_OBJS += builtin/merge-recursive.o +BUILTIN_OBJS += builtin/merge-tree.o +BUILTIN_OBJS += builtin/mktag.o +BUILTIN_OBJS += builtin/mktree.o +BUILTIN_OBJS += builtin/mv.o +BUILTIN_OBJS += builtin/name-rev.o ++BUILTIN_OBJS += builtin/notes.o +BUILTIN_OBJS += builtin/pack-objects.o +BUILTIN_OBJS += builtin/pack-redundant.o +BUILTIN_OBJS += builtin/pack-refs.o +BUILTIN_OBJS += builtin/patch-id.o +BUILTIN_OBJS += builtin/prune-packed.o +BUILTIN_OBJS += builtin/prune.o +BUILTIN_OBJS += builtin/push.o +BUILTIN_OBJS += builtin/read-tree.o +BUILTIN_OBJS += builtin/receive-pack.o +BUILTIN_OBJS += builtin/reflog.o +BUILTIN_OBJS += builtin/remote.o +BUILTIN_OBJS += builtin/replace.o +BUILTIN_OBJS += builtin/rerere.o +BUILTIN_OBJS += builtin/reset.o +BUILTIN_OBJS += builtin/rev-list.o +BUILTIN_OBJS += builtin/rev-parse.o +BUILTIN_OBJS += builtin/revert.o +BUILTIN_OBJS += builtin/rm.o +BUILTIN_OBJS += builtin/send-pack.o +BUILTIN_OBJS += builtin/shortlog.o +BUILTIN_OBJS += builtin/show-branch.o +BUILTIN_OBJS += builtin/show-ref.o +BUILTIN_OBJS += builtin/stripspace.o +BUILTIN_OBJS += builtin/symbolic-ref.o +BUILTIN_OBJS += builtin/tag.o +BUILTIN_OBJS += builtin/tar-tree.o +BUILTIN_OBJS += builtin/unpack-file.o +BUILTIN_OBJS += builtin/unpack-objects.o +BUILTIN_OBJS += builtin/update-index.o +BUILTIN_OBJS += builtin/update-ref.o +BUILTIN_OBJS += builtin/update-server-info.o +BUILTIN_OBJS += builtin/upload-archive.o +BUILTIN_OBJS += builtin/var.o +BUILTIN_OBJS += builtin/verify-pack.o +BUILTIN_OBJS += builtin/verify-tag.o +BUILTIN_OBJS += builtin/write-tree.o GITLIBS = $(LIB_FILE) $(XDIFF_LIB) EXTLIBS = @@@ -728,10 -722,12 +728,10 @@@ ifeq ($(uname_S),Linux) NO_STRLCPY = YesPlease NO_MKSTEMPS = YesPlease - THREADED_DELTA_SEARCH = YesPlease endif ifeq ($(uname_S),GNU/kFreeBSD) NO_STRLCPY = YesPlease NO_MKSTEMPS = YesPlease - THREADED_DELTA_SEARCH = YesPlease endif ifeq ($(uname_S),UnixWare) CC = cc @@@ -785,6 -781,7 +785,6 @@@ ifeq ($(uname_S),Darwin NO_STRLCPY = YesPlease endif NO_MEMMEM = YesPlease - THREADED_DELTA_SEARCH = YesPlease USE_ST_TIMESPEC = YesPlease endif ifeq ($(uname_S),SunOS) @@@ -797,6 -794,7 +797,6 @@@ NO_MKDTEMP = YesPlease NO_MKSTEMPS = YesPlease NO_REGEX = YesPlease - THREADED_DELTA_SEARCH = YesPlease ifeq ($(uname_R),5.7) NEEDS_RESOLV = YesPlease NO_IPV6 = YesPlease @@@ -852,6 -850,7 +852,6 @@@ ifeq ($(uname_S),FreeBSD BASIC_LDFLAGS += -L/usr/local/lib DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease USE_ST_TIMESPEC = YesPlease - THREADED_DELTA_SEARCH = YesPlease ifeq ($(shell expr "$(uname_R)" : '4\.'),2) PTHREAD_LIBS = -pthread NO_UINTMAX_T = YesPlease @@@ -865,6 -864,7 +865,6 @@@ ifeq ($(uname_S),OpenBSD NEEDS_LIBICONV = YesPlease BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib - THREADED_DELTA_SEARCH = YesPlease endif ifeq ($(uname_S),NetBSD) ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2) @@@ -872,6 -872,7 +872,6 @@@ endif BASIC_CFLAGS += -I/usr/pkg/include BASIC_LDFLAGS += -L/usr/pkg/lib $(CC_LD_DYNPATH)/usr/pkg/lib - THREADED_DELTA_SEARCH = YesPlease USE_ST_TIMESPEC = YesPlease NO_MKSTEMPS = YesPlease endif @@@ -886,7 -887,9 +886,7 @@@ ifeq ($(uname_S),AIX INTERNAL_QSORT = UnfortunatelyYes NEEDS_LIBICONV=YesPlease BASIC_CFLAGS += -D_LARGE_FILES - ifneq ($(shell expr "$(uname_V)" : '[1234]'),1) - THREADED_DELTA_SEARCH = YesPlease - else + ifeq ($(shell expr "$(uname_V)" : '[1234]'),1) NO_PTHREADS = YesPlease endif endif @@@ -912,6 -915,7 +912,6 @@@ ifeq ($(uname_S),IRIX SNPRINTF_RETURNS_BOGUS = YesPlease SHELL_PATH = /usr/gnu/bin/bash NEEDS_LIBGEN = YesPlease - THREADED_DELTA_SEARCH = YesPlease endif ifeq ($(uname_S),IRIX64) NO_SETENV=YesPlease @@@ -930,6 -934,7 +930,6 @@@ SNPRINTF_RETURNS_BOGUS = YesPlease SHELL_PATH=/usr/gnu/bin/bash NEEDS_LIBGEN = YesPlease - THREADED_DELTA_SEARCH = YesPlease endif ifeq ($(uname_S),HP-UX) NO_IPV6=YesPlease @@@ -979,6 -984,7 +979,6 @@@ ifeq ($(uname_S),Windows NO_CURL = YesPlease NO_PYTHON = YesPlease BLK_SHA1 = YesPlease - THREADED_DELTA_SEARCH = YesPlease CC = compat/vcbuild/scripts/clink.pl AR = compat/vcbuild/scripts/lib.pl @@@ -988,7 -994,6 +988,7 @@@ COMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\".exe\" BASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib EXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib + PTHREAD_LIBS = lib = ifndef DEBUG BASIC_CFLAGS += -GL -Os -MT @@@ -1030,12 -1035,12 +1030,12 @@@ ifneq (,$(findstring MINGW,$(uname_S)) NO_REGEX = YesPlease NO_PYTHON = YesPlease BLK_SHA1 = YesPlease - THREADED_DELTA_SEARCH = YesPlease - COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch + COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \ compat/win32/pthread.o EXTLIBS += -lws2_32 + PTHREAD_LIBS = X = .exe ifneq (,$(wildcard ../THIS_IS_MSYSGIT)) htmldir=doc/git/html/ @@@ -1052,14 -1057,6 +1052,14 @@@ endi -include config.mak.autogen -include config.mak +ifdef CHECK_HEADER_DEPENDENCIES +USE_COMPUTED_HEADER_DEPENDENCIES = +endif + +ifdef COMPUTE_HEADER_DEPENDENCIES +USE_COMPUTED_HEADER_DEPENDENCIES = YesPlease +endif + ifdef SANE_TOOL_PATH SANE_TOOL_PATH_SQ = $(subst ','\'',$(SANE_TOOL_PATH)) BROKEN_PATH_FIX = 's|^\# @@BROKEN_PATH_FIX@@$$|git_broken_path_fix $(SANE_TOOL_PATH_SQ)|' @@@ -1115,12 -1112,11 +1115,12 @@@ els REMOTE_CURL_PRIMARY = git-remote-http$X REMOTE_CURL_ALIASES = git-remote-https$X git-remote-ftp$X git-remote-ftps$X REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES) - PROGRAMS += $(REMOTE_CURL_NAMES) git-http-fetch$X + PROGRAM_OBJS += http-fetch.o + PROGRAMS += $(REMOTE_CURL_NAMES) curl_check := $(shell (echo 070908; curl-config --vernum) | sort -r | sed -ne 2p) ifeq "$(curl_check)" "070908" ifndef NO_EXPAT - PROGRAMS += git-http-push$X + PROGRAM_OBJS += http-push.o endif endif ifndef NO_EXPAT @@@ -1140,7 -1136,7 +1140,7 @@@ endi EXTLIBS += -lz ifndef NO_POSIX_ONLY_PROGRAMS - PROGRAMS += git-daemon$X + PROGRAM_OBJS += daemon.o endif ifndef NO_OPENSSL OPENSSL_LIBSSL = -lssl @@@ -1241,6 -1237,7 +1241,6 @@@ ifdef NO_MKDTEM endif ifdef NO_MKSTEMPS COMPAT_CFLAGS += -DNO_MKSTEMPS - COMPAT_OBJS += compat/mkstemps.o endif ifdef NO_UNSETENV COMPAT_CFLAGS += -DNO_UNSETENV @@@ -1306,12 -1303,10 +1306,12 @@@ endi ifdef BLK_SHA1 SHA1_HEADER = "block-sha1/sha1.h" LIB_OBJS += block-sha1/sha1.o + LIB_H += block-sha1/sha1.h else ifdef PPC_SHA1 SHA1_HEADER = "ppc/sha1.h" LIB_OBJS += ppc/sha1.o ppc/sha1ppc.o + LIB_H += ppc/sha1.h else SHA1_HEADER = EXTLIBS += $(LIB_4_CRYPTO) @@@ -1337,12 -1332,16 +1337,12 @@@ ifdef RUNTIME_PREFI endif ifdef NO_PTHREADS - THREADED_DELTA_SEARCH = BASIC_CFLAGS += -DNO_PTHREADS else EXTLIBS += $(PTHREAD_LIBS) -endif - -ifdef THREADED_DELTA_SEARCH - BASIC_CFLAGS += -DTHREADED_DELTA_SEARCH LIB_OBJS += thread-utils.o endif + ifdef DIR_HAS_BSD_GROUP_SEMANTICS COMPAT_CFLAGS += -DDIR_HAS_BSD_GROUP_SEMANTICS endif @@@ -1453,7 -1452,7 +1453,7 @@@ export TAR INSTALL DESTDIR SHELL_PAT SHELL = $(SHELL_PATH) -all:: shell_compatibility_test $(ALL_PROGRAMS) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS +all:: shell_compatibility_test $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) $(OTHER_PROGRAMS) GIT-BUILD-OPTIONS ifneq (,$X) $(QUIET_BUILT_IN)$(foreach p,$(patsubst %$X,%,$(filter %$X,$(ALL_PROGRAMS) $(BUILT_INS) git$X)), test -d '$p' -o '$p' -ef '$p$X' || $(RM) '$p';) endif @@@ -1487,8 -1486,8 +1487,8 @@@ git$X: git.o $(BUILTIN_OBJS) $(GITLIBS $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ git.o \ $(BUILTIN_OBJS) $(ALL_LDFLAGS) $(LIBS) -builtin-help.o: common-cmds.h -builtin-help.s builtin-help.o: ALL_CFLAGS += \ +builtin/help.o: common-cmds.h +builtin/help.s builtin/help.o: ALL_CFLAGS += \ '-DGIT_HTML_PATH="$(htmldir_SQ)"' \ '-DGIT_MAN_PATH="$(mandir_SQ)"' \ '-DGIT_INFO_PATH="$(infodir_SQ)"' @@@ -1504,25 -1503,17 +1504,25 @@@ common-cmds.h: ./generate-cmdlist.sh co common-cmds.h: $(wildcard Documentation/git-*.txt) $(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@ +define cmd_munge_script +$(RM) $@ $@+ && \ +sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ + -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \ + -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ + -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ + -e $(BROKEN_PATH_FIX) \ + $@.sh >$@+ +endef + $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh - $(QUIET_GEN)$(RM) $@ $@+ && \ - sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \ - -e 's|@SHELL_PATH@|$(SHELL_PATH_SQ)|' \ - -e 's/@@GIT_VERSION@@/$(GIT_VERSION)/g' \ - -e 's/@@NO_CURL@@/$(NO_CURL)/g' \ - -e $(BROKEN_PATH_FIX) \ - $@.sh >$@+ && \ + $(QUIET_GEN)$(cmd_munge_script) && \ chmod +x $@+ && \ mv $@+ $@ +$(SCRIPT_LIB) : % : %.sh + $(QUIET_GEN)$(cmd_munge_script) && \ + mv $@+ $@ + ifndef NO_PERL $(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak @@@ -1545,11 -1536,6 +1545,11 @@@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % chmod +x $@+ && \ mv $@+ $@ + +.PHONY: gitweb +gitweb: + $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all + ifdef JSMIN OTHER_PROGRAMS += gitweb/gitweb.cgi gitweb/gitweb.min.js gitweb/gitweb.cgi: gitweb/gitweb.perl gitweb/gitweb.min.js @@@ -1557,13 -1543,30 +1557,13 @@@ els OTHER_PROGRAMS += gitweb/gitweb.cgi gitweb/gitweb.cgi: gitweb/gitweb.perl endif - $(QUIET_GEN)$(RM) $@ $@+ && \ - sed -e '1s|#!.*perl|#!$(PERL_PATH_SQ)|' \ - -e 's|++GIT_VERSION++|$(GIT_VERSION)|g' \ - -e 's|++GIT_BINDIR++|$(bindir)|g' \ - -e 's|++GITWEB_CONFIG++|$(GITWEB_CONFIG)|g' \ - -e 's|++GITWEB_CONFIG_SYSTEM++|$(GITWEB_CONFIG_SYSTEM)|g' \ - -e 's|++GITWEB_HOME_LINK_STR++|$(GITWEB_HOME_LINK_STR)|g' \ - -e 's|++GITWEB_SITENAME++|$(GITWEB_SITENAME)|g' \ - -e 's|++GITWEB_PROJECTROOT++|$(GITWEB_PROJECTROOT)|g' \ - -e 's|"++GITWEB_PROJECT_MAXDEPTH++"|$(GITWEB_PROJECT_MAXDEPTH)|g' \ - -e 's|++GITWEB_EXPORT_OK++|$(GITWEB_EXPORT_OK)|g' \ - -e 's|++GITWEB_STRICT_EXPORT++|$(GITWEB_STRICT_EXPORT)|g' \ - -e 's|++GITWEB_BASE_URL++|$(GITWEB_BASE_URL)|g' \ - -e 's|++GITWEB_LIST++|$(GITWEB_LIST)|g' \ - -e 's|++GITWEB_HOMETEXT++|$(GITWEB_HOMETEXT)|g' \ - -e 's|++GITWEB_CSS++|$(GITWEB_CSS)|g' \ - -e 's|++GITWEB_LOGO++|$(GITWEB_LOGO)|g' \ - -e 's|++GITWEB_FAVICON++|$(GITWEB_FAVICON)|g' \ - -e 's|++GITWEB_JS++|$(GITWEB_JS)|g' \ - -e 's|++GITWEB_SITE_HEADER++|$(GITWEB_SITE_HEADER)|g' \ - -e 's|++GITWEB_SITE_FOOTER++|$(GITWEB_SITE_FOOTER)|g' \ - $< >$@+ && \ - chmod +x $@+ && \ - mv $@+ $@ + $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@) + +ifdef JSMIN +gitweb/gitweb.min.js: gitweb/gitweb.js + $(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) $(patsubst gitweb/%,%,$@) +endif # JSMIN + git-instaweb: git-instaweb.sh gitweb/gitweb.cgi gitweb/gitweb.css gitweb/gitweb.js $(QUIET_GEN)$(RM) $@ $@+ && \ @@@ -1590,6 -1593,12 +1590,6 @@@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git mv $@+ $@ endif # NO_PERL - -ifdef JSMIN -gitweb/gitweb.min.js: gitweb/gitweb.js - $(QUIET_GEN)$(JSMIN) <$< >$@ -endif # JSMIN - ifndef NO_PYTHON $(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS $(patsubst %.py,%,$(SCRIPT_PYTHON)): % : %.py @@@ -1632,140 -1641,19 +1632,140 @@@ git.o git.spec $(patsubst %.perl,%,$(SCRIPT_PERL)) \ : GIT-VERSION-FILE -%.o: %.c GIT-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< +TEST_OBJS := $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS)) +GIT_OBJS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \ + git.o http.o http-walker.o remote-curl.o +XDIFF_OBJS = xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \ + xdiff/xmerge.o xdiff/xpatience.o +OBJECTS := $(GIT_OBJS) $(XDIFF_OBJS) + +dep_files := $(foreach f,$(OBJECTS),$(dir $f).depend/$(notdir $f).d) +dep_dirs := $(addsuffix .depend,$(sort $(dir $(OBJECTS)))) + +ifdef COMPUTE_HEADER_DEPENDENCIES +$(dep_dirs): + mkdir -p $@ + +missing_dep_dirs := $(filter-out $(wildcard $(dep_dirs)),$(dep_dirs)) +dep_file = $(dir $@).depend/$(notdir $@).d +dep_args = -MF $(dep_file) -MMD -MP +ifdef CHECK_HEADER_DEPENDENCIES +$(error cannot compute header dependencies outside a normal build. \ +Please unset CHECK_HEADER_DEPENDENCIES and try again) +endif +endif + +ifndef COMPUTE_HEADER_DEPENDENCIES +ifndef CHECK_HEADER_DEPENDENCIES +dep_dirs = +missing_dep_dirs = +dep_args = +endif +endif + +ifdef CHECK_HEADER_DEPENDENCIES +ifndef PRINT_HEADER_DEPENDENCIES +missing_deps = $(filter-out $(notdir $^), \ + $(notdir $(shell $(MAKE) -s $@ \ + CHECK_HEADER_DEPENDENCIES=YesPlease \ + USE_COMPUTED_HEADER_DEPENDENCIES=YesPlease \ + PRINT_HEADER_DEPENDENCIES=YesPlease))) +endif +endif + +ASM_SRC := $(wildcard $(OBJECTS:o=S)) +ASM_OBJ := $(ASM_SRC:S=o) +C_OBJ := $(filter-out $(ASM_OBJ),$(OBJECTS)) + +.SUFFIXES: + +ifdef PRINT_HEADER_DEPENDENCIES +$(C_OBJ): %.o: %.c FORCE + echo $^ +$(ASM_OBJ): %.o: %.S FORCE + echo $^ + +ifndef CHECK_HEADER_DEPENDENCIES +$(error cannot print header dependencies during a normal build. \ +Please set CHECK_HEADER_DEPENDENCIES and try again) +endif +endif + +ifndef PRINT_HEADER_DEPENDENCIES +ifdef CHECK_HEADER_DEPENDENCIES +$(C_OBJ): %.o: %.c $(dep_files) FORCE + @set -e; echo CHECK $@; \ + missing_deps="$(missing_deps)"; \ + if test "$$missing_deps"; \ + then \ + echo missing dependencies: $$missing_deps; \ + false; \ + fi +$(ASM_OBJ): %.o: %.S $(dep_files) FORCE + @set -e; echo CHECK $@; \ + missing_deps="$(missing_deps)"; \ + if test "$$missing_deps"; \ + then \ + echo missing dependencies: $$missing_deps; \ + false; \ + fi +endif +endif + +ifndef CHECK_HEADER_DEPENDENCIES +$(C_OBJ): %.o: %.c GIT-CFLAGS $(missing_dep_dirs) + $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $< +$(ASM_OBJ): %.o: %.S GIT-CFLAGS $(missing_dep_dirs) + $(QUIET_CC)$(CC) -o $*.o -c $(dep_args) $(ALL_CFLAGS) $< +endif + %.s: %.c GIT-CFLAGS FORCE $(QUIET_CC)$(CC) -S $(ALL_CFLAGS) $< -%.o: %.S GIT-CFLAGS - $(QUIET_CC)$(CC) -o $*.o -c $(ALL_CFLAGS) $< + +ifdef USE_COMPUTED_HEADER_DEPENDENCIES +# Take advantage of gcc's on-the-fly dependency generation +# See . +dep_files_present := $(wildcard $(dep_files)) +ifneq ($(dep_files_present),) +include $(dep_files_present) +endif +else +# Dependencies on header files, for platforms that do not support +# the gcc -MMD option. +# +# Dependencies on automatically generated headers such as common-cmds.h +# should _not_ be included here, since they are necessary even when +# building an object for the first time. +# +# XXX. Please check occasionally that these include all dependencies +# gcc detects! + +$(GIT_OBJS): $(LIB_H) +builtin/branch.o builtin/checkout.o builtin/clone.o builtin/reset.o branch.o transport.o: branch.h +builtin/bundle.o bundle.o transport.o: bundle.h +builtin/bisect--helper.o builtin/rev-list.o bisect.o: bisect.h +builtin/clone.o builtin/fetch-pack.o transport.o: fetch-pack.h +builtin/grep.o: thread-utils.h +builtin/send-pack.o transport.o: send-pack.h +builtin/log.o builtin/shortlog.o: shortlog.h +builtin/prune.o builtin/reflog.o reachable.o: reachable.h +builtin/commit.o builtin/revert.o wt-status.o: wt-status.h +builtin/tar-tree.o archive-tar.o: tar.h +builtin/pack-objects.o: thread-utils.h +http-fetch.o http-walker.o remote-curl.o transport.o walker.o: walker.h +http.o http-walker.o http-push.o remote-curl.o: http.h + +xdiff-interface.o $(XDIFF_OBJS): \ + xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \ + xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h +endif exec_cmd.s exec_cmd.o: ALL_CFLAGS += \ '-DGIT_EXEC_PATH="$(gitexecdir_SQ)"' \ '-DBINDIR="$(bindir_relative_SQ)"' \ '-DPREFIX="$(prefix_SQ)"' -builtin-init-db.s builtin-init-db.o: ALL_CFLAGS += \ +builtin/init-db.s builtin/init-db.o: ALL_CFLAGS += \ -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' config.s config.o: ALL_CFLAGS += -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' @@@ -1773,6 -1661,7 +1773,6 @@@ http.s http.o: ALL_CFLAGS += -DGIT_USER_AGENT='"git/$(GIT_VERSION)"' ifdef NO_EXPAT -http-walker.o: http.h http-walker.s http-walker.o: ALL_CFLAGS += -DNO_EXPAT endif @@@ -1783,6 -1672,10 +1783,6 @@@ git-imap-send$X: imap-send.o $(GITLIBS $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(OPENSSL_LINK) $(OPENSSL_LIBSSL) -http.o http-walker.o http-push.o: http.h - -http.o http-walker.o: $(LIB_H) - git-http-fetch$X: revision.o http.o http-walker.o http-fetch.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) @@@ -1800,9 -1693,18 +1800,9 @@@ $(REMOTE_CURL_PRIMARY): remote-curl.o h $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(CURL_LIBCURL) $(EXPAT_LIBEXPAT) -$(LIB_OBJS) $(BUILTIN_OBJS): $(LIB_H) -$(patsubst git-%$X,%.o,$(PROGRAMS)) git.o: $(LIB_H) $(wildcard */*.h) -builtin-revert.o wt-status.o: wt-status.h - $(LIB_FILE): $(LIB_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(LIB_OBJS) -XDIFF_OBJS=xdiff/xdiffi.o xdiff/xprepare.o xdiff/xutils.o xdiff/xemit.o \ - xdiff/xmerge.o xdiff/xpatience.o -$(XDIFF_OBJS): xdiff/xinclude.h xdiff/xmacros.h xdiff/xdiff.h xdiff/xtypes.h \ - xdiff/xutils.h xdiff/xprepare.h xdiff/xdiffi.h xdiff/xemit.h - $(XDIFF_LIB): $(XDIFF_OBJS) $(QUIET_AR)$(RM) $@ && $(AR) rcs $@ $(XDIFF_OBJS) @@@ -1868,6 -1770,24 +1868,6 @@@ GIT-GUI-VARS: FORC fi endif -### Testing rules - -TEST_PROGRAMS_NEED_X += test-chmtime -TEST_PROGRAMS_NEED_X += test-ctype -TEST_PROGRAMS_NEED_X += test-date -TEST_PROGRAMS_NEED_X += test-delta -TEST_PROGRAMS_NEED_X += test-dump-cache-tree -TEST_PROGRAMS_NEED_X += test-genrandom -TEST_PROGRAMS_NEED_X += test-match-trees -TEST_PROGRAMS_NEED_X += test-parse-options -TEST_PROGRAMS_NEED_X += test-path-utils -TEST_PROGRAMS_NEED_X += test-run-command -TEST_PROGRAMS_NEED_X += test-sha1 -TEST_PROGRAMS_NEED_X += test-sigchain -TEST_PROGRAMS_NEED_X += test-index-version - -TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X)) - test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X)) all:: $(TEST_PROGRAMS) $(test_bindir_programs) @@@ -1885,8 -1805,6 +1885,8 @@@ bin-wrappers/%: wrap-for-bin.s export NO_SVN_TESTS +### Testing rules + test: all $(MAKE) -C t/ all @@@ -1898,7 -1816,9 +1898,7 @@@ test-delta$X: diff-delta.o patch-delta. test-parse-options$X: parse-options.o -test-parse-options.o: parse-options.h - -.PRECIOUS: $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS)) +.PRECIOUS: $(TEST_OBJS) test-%$X: test-%.o $(GITLIBS) $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(LIBS) @@@ -1944,7 -1864,6 +1944,7 @@@ install: al $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(bindir_SQ)' $(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' $(INSTALL) $(ALL_PROGRAMS) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' + $(INSTALL) -m 644 $(SCRIPT_LIB) '$(DESTDIR_SQ)$(gitexec_instdir_SQ)' $(INSTALL) $(install_bindir_programs) '$(DESTDIR_SQ)$(bindir_SQ)' $(MAKE) -C templates DESTDIR='$(DESTDIR_SQ)' install ifndef NO_PERL @@@ -2063,11 -1982,10 +2063,11 @@@ distclean: clea clean: $(RM) *.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o xdiff/*.o \ - $(LIB_FILE) $(XDIFF_LIB) - $(RM) $(ALL_PROGRAMS) $(BUILT_INS) git$X + builtin/*.o $(LIB_FILE) $(XDIFF_LIB) + $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X $(RM) $(TEST_PROGRAMS) $(RM) -r bin-wrappers + $(RM) -r $(dep_dirs) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo common-cmds.h TAGS tags cscope* $(RM) -r autom4te.cache $(RM) config.log config.mak.autogen config.mak.append config.status config.cache @@@ -2097,13 -2015,12 +2097,13 @@@ endi ### Check documentation # check-docs:: - @(for v in $(ALL_PROGRAMS) $(BUILT_INS) git gitk; \ + @(for v in $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk; \ do \ case "$$v" in \ git-merge-octopus | git-merge-ours | git-merge-recursive | \ git-merge-resolve | git-merge-subtree | \ git-fsck-objects | git-init-db | \ + git-remote-* | git-stage | \ git-?*--?* ) continue ;; \ esac ; \ test -f "Documentation/$$v.txt" || \ @@@ -2141,12 -2058,9 +2141,12 @@@ documented,gitrepository-layout | \ documented,gittutorial | \ documented,gittutorial-2 | \ + documented,git-bisect-lk2009 | \ + documented,git-remote-helpers | \ + documented,gitworkflows | \ sentinel,not,matching,is,ok ) continue ;; \ esac; \ - case " $(ALL_PROGRAMS) $(BUILT_INS) git gitk " in \ + case " $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git gitk " in \ *" $$cmd "*) ;; \ *) echo "removed but $$how: $$cmd" ;; \ esac; \ diff --combined builtin/notes.c index 0000000000,0000000000..feb710ac4a new file mode 100644 --- /dev/null +++ b/builtin/notes.c @@@ -1,0 -1,0 +1,455 @@@ ++/* ++ * Builtin "git notes" ++ * ++ * Copyright (c) 2010 Johan Herland ++ * ++ * Based on git-notes.sh by Johannes Schindelin, ++ * and builtin-tag.c by Kristian Høgsberg and Carlos Rica. ++ */ ++ ++#include "cache.h" ++#include "builtin.h" ++#include "notes.h" ++#include "blob.h" ++#include "commit.h" ++#include "refs.h" ++#include "exec_cmd.h" ++#include "run-command.h" ++#include "parse-options.h" ++ ++static const char * const git_notes_usage[] = { ++ "git notes [list []]", ++ "git notes add [-f] [-m | -F | (-c | -C) ] []", ++ "git notes copy [-f] ", ++ "git notes append [-m | -F | (-c | -C) ] []", ++ "git notes edit []", ++ "git notes show []", ++ "git notes remove []", ++ "git notes prune", ++ NULL ++}; ++ ++static const char note_template[] = ++ "\n" ++ "#\n" ++ "# Write/edit the notes for the following object:\n" ++ "#\n"; ++ ++struct msg_arg { ++ int given; ++ int use_editor; ++ struct strbuf buf; ++}; ++ ++static int list_each_note(const unsigned char *object_sha1, ++ const unsigned char *note_sha1, char *note_path, ++ void *cb_data) ++{ ++ printf("%s %s\n", sha1_to_hex(note_sha1), sha1_to_hex(object_sha1)); ++ return 0; ++} ++ ++static void write_note_data(int fd, const unsigned char *sha1) ++{ ++ unsigned long size; ++ enum object_type type; ++ char *buf = read_sha1_file(sha1, &type, &size); ++ if (buf) { ++ if (size) ++ write_or_die(fd, buf, size); ++ free(buf); ++ } ++} ++ ++static void write_commented_object(int fd, const unsigned char *object) ++{ ++ const char *show_args[5] = ++ {"show", "--stat", "--no-notes", sha1_to_hex(object), NULL}; ++ struct child_process show; ++ struct strbuf buf = STRBUF_INIT; ++ FILE *show_out; ++ ++ /* Invoke "git show --stat --no-notes $object" */ ++ memset(&show, 0, sizeof(show)); ++ show.argv = show_args; ++ show.no_stdin = 1; ++ show.out = -1; ++ show.err = 0; ++ show.git_cmd = 1; ++ if (start_command(&show)) ++ die("unable to start 'show' for object '%s'", ++ sha1_to_hex(object)); ++ ++ /* Open the output as FILE* so strbuf_getline() can be used. */ ++ show_out = xfdopen(show.out, "r"); ++ if (show_out == NULL) ++ die_errno("can't fdopen 'show' output fd"); ++ ++ /* Prepend "# " to each output line and write result to 'fd' */ ++ while (strbuf_getline(&buf, show_out, '\n') != EOF) { ++ write_or_die(fd, "# ", 2); ++ write_or_die(fd, buf.buf, buf.len); ++ write_or_die(fd, "\n", 1); ++ } ++ strbuf_release(&buf); ++ if (fclose(show_out)) ++ die_errno("failed to close pipe to 'show' for object '%s'", ++ sha1_to_hex(object)); ++ if (finish_command(&show)) ++ die("failed to finish 'show' for object '%s'", ++ sha1_to_hex(object)); ++} ++ ++static void create_note(const unsigned char *object, struct msg_arg *msg, ++ int append_only, const unsigned char *prev, ++ unsigned char *result) ++{ ++ char *path = NULL; ++ ++ if (msg->use_editor || !msg->given) { ++ int fd; ++ ++ /* write the template message before editing: */ ++ path = git_pathdup("NOTES_EDITMSG"); ++ fd = open(path, O_CREAT | O_TRUNC | O_WRONLY, 0600); ++ if (fd < 0) ++ die_errno("could not create file '%s'", path); ++ ++ if (msg->given) ++ write_or_die(fd, msg->buf.buf, msg->buf.len); ++ else if (prev && !append_only) ++ write_note_data(fd, prev); ++ write_or_die(fd, note_template, strlen(note_template)); ++ ++ write_commented_object(fd, object); ++ ++ close(fd); ++ strbuf_reset(&(msg->buf)); ++ ++ if (launch_editor(path, &(msg->buf), NULL)) { ++ die("Please supply the note contents using either -m" \ ++ " or -F option"); ++ } ++ stripspace(&(msg->buf), 1); ++ } ++ ++ if (prev && append_only) { ++ /* Append buf to previous note contents */ ++ unsigned long size; ++ enum object_type type; ++ char *prev_buf = read_sha1_file(prev, &type, &size); ++ ++ strbuf_grow(&(msg->buf), size + 1); ++ if (msg->buf.len && prev_buf && size) ++ strbuf_insert(&(msg->buf), 0, "\n", 1); ++ if (prev_buf && size) ++ strbuf_insert(&(msg->buf), 0, prev_buf, size); ++ free(prev_buf); ++ } ++ ++ if (!msg->buf.len) { ++ fprintf(stderr, "Removing note for object %s\n", ++ sha1_to_hex(object)); ++ hashclr(result); ++ } else { ++ if (write_sha1_file(msg->buf.buf, msg->buf.len, blob_type, result)) { ++ error("unable to write note object"); ++ if (path) ++ error("The note contents has been left in %s", ++ path); ++ exit(128); ++ } ++ } ++ ++ if (path) { ++ unlink_or_warn(path); ++ free(path); ++ } ++} ++ ++static int parse_msg_arg(const struct option *opt, const char *arg, int unset) ++{ ++ struct msg_arg *msg = opt->value; ++ ++ strbuf_grow(&(msg->buf), strlen(arg) + 2); ++ if (msg->buf.len) ++ strbuf_addch(&(msg->buf), '\n'); ++ strbuf_addstr(&(msg->buf), arg); ++ stripspace(&(msg->buf), 0); ++ ++ msg->given = 1; ++ return 0; ++} ++ ++static int parse_file_arg(const struct option *opt, const char *arg, int unset) ++{ ++ struct msg_arg *msg = opt->value; ++ ++ if (msg->buf.len) ++ strbuf_addch(&(msg->buf), '\n'); ++ if (!strcmp(arg, "-")) { ++ if (strbuf_read(&(msg->buf), 0, 1024) < 0) ++ die_errno("cannot read '%s'", arg); ++ } else if (strbuf_read_file(&(msg->buf), arg, 1024) < 0) ++ die_errno("could not open or read '%s'", arg); ++ stripspace(&(msg->buf), 0); ++ ++ msg->given = 1; ++ return 0; ++} ++ ++static int parse_reuse_arg(const struct option *opt, const char *arg, int unset) ++{ ++ struct msg_arg *msg = opt->value; ++ char *buf; ++ unsigned char object[20]; ++ enum object_type type; ++ unsigned long len; ++ ++ if (msg->buf.len) ++ strbuf_addch(&(msg->buf), '\n'); ++ ++ if (get_sha1(arg, object)) ++ die("Failed to resolve '%s' as a valid ref.", arg); ++ if (!(buf = read_sha1_file(object, &type, &len)) || !len) { ++ free(buf); ++ die("Failed to read object '%s'.", arg);; ++ } ++ strbuf_add(&(msg->buf), buf, len); ++ free(buf); ++ ++ msg->given = 1; ++ return 0; ++} ++ ++static int parse_reedit_arg(const struct option *opt, const char *arg, int unset) ++{ ++ struct msg_arg *msg = opt->value; ++ msg->use_editor = 1; ++ return parse_reuse_arg(opt, arg, unset); ++} ++ ++int commit_notes(struct notes_tree *t, const char *msg) ++{ ++ struct commit_list *parent; ++ unsigned char tree_sha1[20], prev_commit[20], new_commit[20]; ++ struct strbuf buf = STRBUF_INIT; ++ ++ if (!t) ++ t = &default_notes_tree; ++ if (!t->initialized || !t->ref || !*t->ref) ++ die("Cannot commit uninitialized/unreferenced notes tree"); ++ ++ /* Prepare commit message and reflog message */ ++ strbuf_addstr(&buf, "notes: "); /* commit message starts at index 7 */ ++ strbuf_addstr(&buf, msg); ++ if (buf.buf[buf.len - 1] != '\n') ++ strbuf_addch(&buf, '\n'); /* Make sure msg ends with newline */ ++ ++ /* Convert notes tree to tree object */ ++ if (write_notes_tree(t, tree_sha1)) ++ die("Failed to write current notes tree to database"); ++ ++ /* Create new commit for the tree object */ ++ if (!read_ref(t->ref, prev_commit)) { /* retrieve parent commit */ ++ parent = xmalloc(sizeof(*parent)); ++ parent->item = lookup_commit(prev_commit); ++ parent->next = NULL; ++ } else { ++ hashclr(prev_commit); ++ parent = NULL; ++ } ++ if (commit_tree(buf.buf + 7, tree_sha1, parent, new_commit, NULL)) ++ die("Failed to commit notes tree to database"); ++ ++ /* Update notes ref with new commit */ ++ update_ref(buf.buf, t->ref, new_commit, prev_commit, 0, DIE_ON_ERR); ++ ++ strbuf_release(&buf); ++ return 0; ++} ++ ++int cmd_notes(int argc, const char **argv, const char *prefix) ++{ ++ struct notes_tree *t; ++ unsigned char object[20], from_obj[20], new_note[20]; ++ const unsigned char *note; ++ const char *object_ref; ++ char logmsg[100]; ++ ++ int list = 0, add = 0, copy = 0, append = 0, edit = 0, show = 0, ++ remove = 0, prune = 0, force = 0; ++ int given_object = 0, i = 1, retval = 0; ++ struct msg_arg msg = { 0, 0, STRBUF_INIT }; ++ struct option options[] = { ++ OPT_GROUP("Notes contents options"), ++ { OPTION_CALLBACK, 'm', "message", &msg, "MSG", ++ "note contents as a string", PARSE_OPT_NONEG, ++ parse_msg_arg}, ++ { OPTION_CALLBACK, 'F', "file", &msg, "FILE", ++ "note contents in a file", PARSE_OPT_NONEG, ++ parse_file_arg}, ++ { OPTION_CALLBACK, 'c', "reedit-message", &msg, "OBJECT", ++ "reuse and edit specified note object", PARSE_OPT_NONEG, ++ parse_reedit_arg}, ++ { OPTION_CALLBACK, 'C', "reuse-message", &msg, "OBJECT", ++ "reuse specified note object", PARSE_OPT_NONEG, ++ parse_reuse_arg}, ++ OPT_GROUP("Other options"), ++ OPT_BOOLEAN('f', "force", &force, "replace existing notes"), ++ OPT_END() ++ }; ++ ++ git_config(git_default_config, NULL); ++ ++ argc = parse_options(argc, argv, prefix, options, git_notes_usage, 0); ++ ++ if (argc && !strcmp(argv[0], "list")) ++ list = 1; ++ else if (argc && !strcmp(argv[0], "add")) ++ add = 1; ++ else if (argc && !strcmp(argv[0], "copy")) ++ copy = 1; ++ else if (argc && !strcmp(argv[0], "append")) ++ append = 1; ++ else if (argc && !strcmp(argv[0], "edit")) ++ edit = 1; ++ else if (argc && !strcmp(argv[0], "show")) ++ show = 1; ++ else if (argc && !strcmp(argv[0], "remove")) ++ remove = 1; ++ else if (argc && !strcmp(argv[0], "prune")) ++ prune = 1; ++ else if (!argc) { ++ list = 1; /* Default to 'list' if no other subcommand given */ ++ i = 0; ++ } ++ ++ if (list + add + copy + append + edit + show + remove + prune != 1) ++ usage_with_options(git_notes_usage, options); ++ ++ if (msg.given && !(add || append || edit)) { ++ error("cannot use -m/-F/-c/-C options with %s subcommand.", ++ argv[0]); ++ usage_with_options(git_notes_usage, options); ++ } ++ ++ if (msg.given && edit) { ++ fprintf(stderr, "The -m/-F/-c/-C options have been deprecated " ++ "for the 'edit' subcommand.\n" ++ "Please use 'git notes add -f -m/-F/-c/-C' instead.\n"); ++ } ++ ++ if (force && !(add || copy)) { ++ error("cannot use -f option with %s subcommand.", argv[0]); ++ usage_with_options(git_notes_usage, options); ++ } ++ ++ if (copy) { ++ const char *from_ref; ++ if (argc < 3) { ++ error("too few parameters"); ++ usage_with_options(git_notes_usage, options); ++ } ++ from_ref = argv[i++]; ++ if (get_sha1(from_ref, from_obj)) ++ die("Failed to resolve '%s' as a valid ref.", from_ref); ++ } ++ ++ given_object = argc > i; ++ object_ref = given_object ? argv[i++] : "HEAD"; ++ ++ if (argc > i || (prune && given_object)) { ++ error("too many parameters"); ++ usage_with_options(git_notes_usage, options); ++ } ++ ++ if (get_sha1(object_ref, object)) ++ die("Failed to resolve '%s' as a valid ref.", object_ref); ++ ++ init_notes(NULL, NULL, NULL, 0); ++ t = &default_notes_tree; ++ ++ if (prefixcmp(t->ref, "refs/notes/")) ++ die("Refusing to %s notes in %s (outside of refs/notes/)", ++ argv[0], t->ref); ++ ++ note = get_note(t, object); ++ ++ /* list command */ ++ ++ if (list) { ++ if (given_object) { ++ if (note) { ++ puts(sha1_to_hex(note)); ++ goto end; ++ } ++ } else { ++ retval = for_each_note(t, 0, list_each_note, NULL); ++ goto end; ++ } ++ } ++ ++ /* show command */ ++ ++ if ((list || show) && !note) { ++ error("No note found for object %s.", sha1_to_hex(object)); ++ retval = 1; ++ goto end; ++ } else if (show) { ++ const char *show_args[3] = {"show", sha1_to_hex(note), NULL}; ++ retval = execv_git_cmd(show_args); ++ goto end; ++ } ++ ++ /* add/append/edit/remove/prune command */ ++ ++ if ((add || copy) && note) { ++ if (!force) { ++ error("Cannot %s notes. Found existing notes for object" ++ " %s. Use '-f' to overwrite existing notes", ++ argv[0], sha1_to_hex(object)); ++ retval = 1; ++ goto end; ++ } ++ fprintf(stderr, "Overwriting existing notes for object %s\n", ++ sha1_to_hex(object)); ++ } ++ ++ if (remove) { ++ msg.given = 1; ++ msg.use_editor = 0; ++ strbuf_reset(&(msg.buf)); ++ } ++ ++ if (prune) { ++ hashclr(new_note); ++ prune_notes(t); ++ goto commit; ++ } else if (copy) { ++ const unsigned char *from_note = get_note(t, from_obj); ++ if (!from_note) { ++ error("Missing notes on source object %s. Cannot copy.", ++ sha1_to_hex(from_obj)); ++ retval = 1; ++ goto end; ++ } ++ hashcpy(new_note, from_note); ++ } else ++ create_note(object, &msg, append, note, new_note); ++ ++ if (is_null_sha1(new_note)) ++ remove_note(t, object); ++ else ++ add_note(t, object, new_note, combine_notes_overwrite); ++ ++commit: ++ snprintf(logmsg, sizeof(logmsg), "Notes %s by 'git notes %s'", ++ is_null_sha1(new_note) ? "removed" : "added", argv[0]); ++ commit_notes(t, logmsg); ++ ++end: ++ free_notes(t); ++ strbuf_release(&(msg.buf)); ++ return retval; ++} diff --combined git.c index f09948eed9,32f76e15ea..6bae30545b --- a/git.c +++ b/git.c @@@ -54,9 -54,6 +54,9 @@@ static int handle_options(const char ** { int handled = 0; + if (!getenv("GIT_ASKPASS") && getenv("SSH_ASKPASS")) + setenv("GIT_ASKPASS", getenv("SSH_ASKPASS"), 1); + while (*argc > 0) { const char *cmd = (*argv)[0]; if (cmd[0] != '-') @@@ -346,6 -343,7 +346,7 @@@ static void handle_internal_command(in { "mktree", cmd_mktree, RUN_SETUP }, { "mv", cmd_mv, RUN_SETUP | NEED_WORK_TREE }, { "name-rev", cmd_name_rev, RUN_SETUP }, + { "notes", cmd_notes, RUN_SETUP }, { "pack-objects", cmd_pack_objects, RUN_SETUP }, { "pack-redundant", cmd_pack_redundant, RUN_SETUP }, { "patch-id", cmd_patch_id }, @@@ -530,7 -528,7 +531,7 @@@ int main(int argc, const char **argv break; if (was_alias) { fprintf(stderr, "Expansion of alias '%s' failed; " - "'%s' is not a git-command\n", + "'%s' is not a git command\n", cmd, argv[0]); exit(1); } diff --combined t/t3301-notes.sh index 714626d2d6,90178f96d2..37b96871c5 --- a/t/t3301-notes.sh +++ b/t/t3301-notes.sh @@@ -8,16 -8,15 +8,16 @@@ test_description='Test commit notes . ./test-lib.sh cat > fake_editor.sh << \EOF +#!/bin/sh echo "$MSG" > "$1" echo "$MSG" >& 2 EOF chmod a+x fake_editor.sh - VISUAL=./fake_editor.sh - export VISUAL + GIT_EDITOR=./fake_editor.sh + export GIT_EDITOR test_expect_success 'cannot annotate non-existing HEAD' ' - (MSG=3 && export MSG && test_must_fail git notes edit) + (MSG=3 && export MSG && test_must_fail git notes add) ' test_expect_success setup ' @@@ -33,18 -32,18 +33,18 @@@ test_expect_success 'need valid notes ref' ' (MSG=1 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF && - test_must_fail git notes edit) && + test_must_fail git notes add) && (MSG=2 GIT_NOTES_REF=/ && export MSG GIT_NOTES_REF && test_must_fail git notes show) ' - test_expect_success 'refusing to edit in refs/heads/' ' + test_expect_success 'refusing to add notes in refs/heads/' ' (MSG=1 GIT_NOTES_REF=refs/heads/bogus && export MSG GIT_NOTES_REF && - test_must_fail git notes edit) + test_must_fail git notes add) ' - test_expect_success 'refusing to edit in refs/remotes/' ' + test_expect_success 'refusing to edit notes in refs/remotes/' ' (MSG=1 GIT_NOTES_REF=refs/remotes/bogus && export MSG GIT_NOTES_REF && test_must_fail git notes edit) @@@ -57,8 -56,35 +57,35 @@@ test_expect_success 'handle empty note test_expect_success 'create notes' ' git config core.notesRef refs/notes/commits && - MSG=b1 git notes edit && - test ! -f .git/new-notes && + MSG=b4 git notes add && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b4 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ + ' + + test_expect_success 'edit existing notes' ' + MSG=b3 git notes edit && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b3 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ + ' + + test_expect_success 'cannot add note where one exists' ' + ! MSG=b2 git notes add && + test ! -f .git/NOTES_EDITMSG && + test 1 = $(git ls-tree refs/notes/commits | wc -l) && + test b3 = $(git notes show) && + git show HEAD^ && + test_must_fail git notes show HEAD^ + ' + + test_expect_success 'can overwrite existing note with "git notes add -f"' ' + MSG=b1 git notes add -f && + test ! -f .git/NOTES_EDITMSG && test 1 = $(git ls-tree refs/notes/commits | wc -l) && test b1 = $(git notes show) && git show HEAD^ && @@@ -81,6 -107,7 +108,7 @@@ test_expect_success 'show notes' git log -1 > output && test_cmp expect output ' + test_expect_success 'create multi-line notes (setup)' ' : > a3 && git add a3 && @@@ -88,7 -115,7 +116,7 @@@ git commit -m 3rd && MSG="b3 c3c3c3c3 - d3d3d3" git notes edit + d3d3d3" git notes add ' cat > expect-multiline << EOF @@@ -111,19 -138,16 +139,16 @@@ test_expect_success 'show multi-line no git log -2 > output && test_cmp expect-multiline output ' - test_expect_success 'create -m and -F notes (setup)' ' + test_expect_success 'create -F notes (setup)' ' : > a4 && git add a4 && test_tick && git commit -m 4th && echo "xyzzy" > note5 && - git notes edit -m spam -F note5 -m "foo - bar - baz" + git notes add -F note5 ' - whitespace=" " - cat > expect-m-and-F << EOF + cat > expect-F << EOF commit 15023535574ded8b1a89052b32673f84cf9582b8 Author: A U Thor Date: Thu Apr 7 15:16:13 2005 -0700 @@@ -131,21 -155,15 +156,15 @@@ 4th Notes: - spam - $whitespace xyzzy - $whitespace - foo - bar - baz EOF - printf "\n" >> expect-m-and-F - cat expect-multiline >> expect-m-and-F + printf "\n" >> expect-F + cat expect-multiline >> expect-F - test_expect_success 'show -m and -F notes' ' + test_expect_success 'show -F notes' ' git log -3 > output && - test_cmp expect-m-and-F output + test_cmp expect-F output ' cat >expect << EOF @@@ -165,13 -183,7 +184,7 @@@ test_expect_success 'git log --pretty=r cat >>expect <output && @@@ -180,17 -192,17 +193,17 @@@ test_expect_success 'git log --no-notes' ' git log -1 --no-notes >output && - ! grep spam output + ! grep xyzzy output ' test_expect_success 'git format-patch does not show notes' ' git format-patch -1 --stdout >output && - ! grep spam output + ! grep xyzzy output ' test_expect_success 'git format-patch --show-notes does show notes' ' git format-patch --show-notes -1 --stdout >output && - grep spam output + grep xyzzy output ' for pretty in \ @@@ -203,8 -215,433 +216,433 @@@ d esac test_expect_success "git show $pretty does$not show notes" ' git show $p >output && - eval "$negate grep spam output" + eval "$negate grep xyzzy output" ' done + test_expect_success 'create -m notes (setup)' ' + : > a5 && + git add a5 && + test_tick && + git commit -m 5th && + git notes add -m spam -m "foo + bar + baz" + ' + + whitespace=" " + cat > expect-m << EOF + commit bd1753200303d0a0344be813e504253b3d98e74d + Author: A U Thor + Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th + + Notes: + spam + $whitespace + foo + bar + baz + EOF + + printf "\n" >> expect-m + cat expect-F >> expect-m + + test_expect_success 'show -m notes' ' + git log -4 > output && + test_cmp expect-m output + ' + + test_expect_success 'remove note with add -f -F /dev/null (setup)' ' + git notes add -f -F /dev/null + ' + + cat > expect-rm-F << EOF + commit bd1753200303d0a0344be813e504253b3d98e74d + Author: A U Thor + Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th + EOF + + printf "\n" >> expect-rm-F + cat expect-F >> expect-rm-F + + test_expect_success 'verify note removal with -F /dev/null' ' + git log -4 > output && + test_cmp expect-rm-F output && + ! git notes show + ' + + test_expect_success 'do not create empty note with -m "" (setup)' ' + git notes add -m "" + ' + + test_expect_success 'verify non-creation of note with -m ""' ' + git log -4 > output && + test_cmp expect-rm-F output && + ! git notes show + ' + + cat > expect-combine_m_and_F << EOF + foo + + xyzzy + + bar + + zyxxy + + baz + EOF + + test_expect_success 'create note with combination of -m and -F' ' + echo "xyzzy" > note_a && + echo "zyxxy" > note_b && + git notes add -m "foo" -F note_a -m "bar" -F note_b -m "baz" && + git notes show > output && + test_cmp expect-combine_m_and_F output + ' + + test_expect_success 'remove note with "git notes remove" (setup)' ' + git notes remove HEAD^ && + git notes remove + ' + + cat > expect-rm-remove << EOF + commit bd1753200303d0a0344be813e504253b3d98e74d + Author: A U Thor + Date: Thu Apr 7 15:17:13 2005 -0700 + + 5th + + commit 15023535574ded8b1a89052b32673f84cf9582b8 + Author: A U Thor + Date: Thu Apr 7 15:16:13 2005 -0700 + + 4th + EOF + + printf "\n" >> expect-rm-remove + cat expect-multiline >> expect-rm-remove + + test_expect_success 'verify note removal with "git notes remove"' ' + git log -4 > output && + test_cmp expect-rm-remove output && + ! git notes show HEAD^ + ' + + cat > expect << EOF + c18dc024e14f08d18d14eea0d747ff692d66d6a3 1584215f1d29c65e99c6c6848626553fdd07fd75 + c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 268048bfb8a1fb38e703baceb8ab235421bf80c5 + EOF + + test_expect_success 'list notes with "git notes list"' ' + git notes list > output && + test_cmp expect output + ' + + test_expect_success 'list notes with "git notes"' ' + git notes > output && + test_cmp expect output + ' + + cat > expect << EOF + c18dc024e14f08d18d14eea0d747ff692d66d6a3 + EOF + + test_expect_success 'list specific note with "git notes list "' ' + git notes list HEAD^^ > output && + test_cmp expect output + ' + + cat > expect << EOF + EOF + + test_expect_success 'listing non-existing notes fails' ' + test_must_fail git notes list HEAD > output && + test_cmp expect output + ' + + cat > expect << EOF + Initial set of notes + + More notes appended with git notes append + EOF + + test_expect_success 'append to existing note with "git notes append"' ' + git notes add -m "Initial set of notes" && + git notes append -m "More notes appended with git notes append" && + git notes show > output && + test_cmp expect output + ' + + test_expect_success 'appending empty string does not change existing note' ' + git notes append -m "" && + git notes show > output && + test_cmp expect output + ' + + test_expect_success 'git notes append == add when there is no existing note' ' + git notes remove HEAD && + test_must_fail git notes list HEAD && + git notes append -m "Initial set of notes + + More notes appended with git notes append" && + git notes show > output && + test_cmp expect output + ' + + test_expect_success 'appending empty string to non-existing note does not create note' ' + git notes remove HEAD && + test_must_fail git notes list HEAD && + git notes append -m "" && + test_must_fail git notes list HEAD + ' + + test_expect_success 'create other note on a different notes ref (setup)' ' + : > a6 && + git add a6 && + test_tick && + git commit -m 6th && + GIT_NOTES_REF="refs/notes/other" git notes add -m "other note" + ' + + cat > expect-other << EOF + commit 387a89921c73d7ed72cd94d179c1c7048ca47756 + Author: A U Thor + Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th + + Notes: + other note + EOF + + cat > expect-not-other << EOF + commit 387a89921c73d7ed72cd94d179c1c7048ca47756 + Author: A U Thor + Date: Thu Apr 7 15:18:13 2005 -0700 + + 6th + EOF + + test_expect_success 'Do not show note on other ref by default' ' + git log -1 > output && + test_cmp expect-not-other output + ' + + test_expect_success 'Do show note when ref is given in GIT_NOTES_REF' ' + GIT_NOTES_REF="refs/notes/other" git log -1 > output && + test_cmp expect-other output + ' + + test_expect_success 'Do show note when ref is given in core.notesRef config' ' + git config core.notesRef "refs/notes/other" && + git log -1 > output && + test_cmp expect-other output + ' + + test_expect_success 'Do not show note when core.notesRef is overridden' ' + GIT_NOTES_REF="refs/notes/wrong" git log -1 > output && + test_cmp expect-not-other output + ' + + test_expect_success 'Allow notes on non-commits (trees, blobs, tags)' ' + echo "Note on a tree" > expect + git notes add -m "Note on a tree" HEAD: && + git notes show HEAD: > actual && + test_cmp expect actual && + echo "Note on a blob" > expect + filename=$(git ls-tree --name-only HEAD | head -n1) && + git notes add -m "Note on a blob" HEAD:$filename && + git notes show HEAD:$filename > actual && + test_cmp expect actual && + echo "Note on a tag" > expect + git tag -a -m "This is an annotated tag" foobar HEAD^ && + git notes add -m "Note on a tag" foobar && + git notes show foobar > actual && + test_cmp expect actual + ' + + cat > expect << EOF + commit 2ede89468182a62d0bde2583c736089bcf7d7e92 + Author: A U Thor + Date: Thu Apr 7 15:19:13 2005 -0700 + + 7th + + Notes: + other note + EOF + + test_expect_success 'create note from other note with "git notes add -C"' ' + : > a7 && + git add a7 && + test_tick && + git commit -m 7th && + git notes add -C $(git notes list HEAD^) && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD^)" + ' + + test_expect_success 'create note from non-existing note with "git notes add -C" fails' ' + : > a8 && + git add a8 && + test_tick && + git commit -m 8th && + test_must_fail git notes add -C deadbeef && + test_must_fail git notes list HEAD + ' + + cat > expect << EOF + commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b + Author: A U Thor + Date: Thu Apr 7 15:21:13 2005 -0700 + + 9th + + Notes: + yet another note + EOF + + test_expect_success 'create note from other note with "git notes add -c"' ' + : > a9 && + git add a9 && + test_tick && + git commit -m 9th && + MSG="yet another note" git notes add -c $(git notes list HEAD^^) && + git log -1 > actual && + test_cmp expect actual + ' + + test_expect_success 'create note from non-existing note with "git notes add -c" fails' ' + : > a10 && + git add a10 && + test_tick && + git commit -m 10th && + test_must_fail MSG="yet another note" git notes add -c deadbeef && + test_must_fail git notes list HEAD + ' + + cat > expect << EOF + commit 016e982bad97eacdbda0fcbd7ce5b0ba87c81f1b + Author: A U Thor + Date: Thu Apr 7 15:21:13 2005 -0700 + + 9th + + Notes: + yet another note + $whitespace + yet another note + EOF + + test_expect_success 'append to note from other note with "git notes append -C"' ' + git notes append -C $(git notes list HEAD^) HEAD^ && + git log -1 HEAD^ > actual && + test_cmp expect actual + ' + + cat > expect << EOF + commit ffed603236bfa3891c49644257a83598afe8ae5a + Author: A U Thor + Date: Thu Apr 7 15:22:13 2005 -0700 + + 10th + + Notes: + other note + EOF + + test_expect_success 'create note from other note with "git notes append -c"' ' + MSG="other note" git notes append -c $(git notes list HEAD^) && + git log -1 > actual && + test_cmp expect actual + ' + + cat > expect << EOF + commit ffed603236bfa3891c49644257a83598afe8ae5a + Author: A U Thor + Date: Thu Apr 7 15:22:13 2005 -0700 + + 10th + + Notes: + other note + $whitespace + yet another note + EOF + + test_expect_success 'append to note from other note with "git notes append -c"' ' + MSG="yet another note" git notes append -c $(git notes list HEAD) && + git log -1 > actual && + test_cmp expect actual + ' + + cat > expect << EOF + commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be + Author: A U Thor + Date: Thu Apr 7 15:23:13 2005 -0700 + + 11th + + Notes: + other note + $whitespace + yet another note + EOF + + test_expect_success 'copy note with "git notes copy"' ' + : > a11 && + git add a11 && + test_tick && + git commit -m 11th && + git notes copy HEAD^ HEAD && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD^)" + ' + + test_expect_success 'prevent overwrite with "git notes copy"' ' + test_must_fail git notes copy HEAD~2 HEAD && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD^)" + ' + + cat > expect << EOF + commit 6352c5e33dbcab725fe0579be16aa2ba8eb369be + Author: A U Thor + Date: Thu Apr 7 15:23:13 2005 -0700 + + 11th + + Notes: + yet another note + $whitespace + yet another note + EOF + + test_expect_success 'allow overwrite with "git notes copy -f"' ' + git notes copy -f HEAD~2 HEAD && + git log -1 > actual && + test_cmp expect actual && + test "$(git notes list HEAD)" = "$(git notes list HEAD~2)" + ' + + test_expect_success 'cannot copy note from object without notes' ' + : > a12 && + git add a12 && + test_tick && + git commit -m 12th && + : > a13 && + git add a13 && + test_tick && + git commit -m 13th && + test_must_fail git notes copy HEAD^ HEAD + ' + test_done