From c5ae6439d454288a809dd7c916e44ec4a5ae0b3b Mon Sep 17 00:00:00 2001 From: Nanako Shiraishi Date: Thu, 2 Oct 2008 19:14:30 +0900 Subject: commit.c: make read_graft_file() static This function is not called by any other file. Signed-off-by: Nanako Shiraishi Signed-off-by: Shawn O. Pearce --- commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index dc0c5bfdab..c99db162a4 100644 --- a/commit.c +++ b/commit.c @@ -160,7 +160,7 @@ struct commit_graft *read_graft_line(char *buf, int len) return graft; } -int read_graft_file(const char *graft_file) +static int read_graft_file(const char *graft_file) { FILE *fp = fopen(graft_file, "r"); char buf[1024]; -- cgit v1.2.3 From 879ef2485d6ced20845ca626ecb45a9b65aa3a70 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Sat, 20 Dec 2008 13:05:14 +0100 Subject: Introduce commit notes Commit notes are blobs which are shown together with the commit message. These blobs are taken from the notes ref, which you can configure by the config variable core.notesRef, which in turn can be overridden by the environment variable GIT_NOTES_REF. The notes ref is a branch which contains "files" whose names are the names of the corresponding commits (i.e. the SHA-1). The rationale for putting this information into a ref is this: we want to be able to fetch and possibly union-merge the notes, maybe even look at the date when a note was introduced, and we want to store them efficiently together with the other objects. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/config.txt | 15 +++++++++++ Makefile | 2 ++ cache.h | 3 +++ commit.c | 1 + config.c | 5 ++++ environment.c | 1 + notes.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++ notes.h | 7 +++++ pretty.c | 5 ++++ 9 files changed, 107 insertions(+) create mode 100644 notes.c create mode 100644 notes.h (limited to 'commit.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index 21ea16590b..b35a32abe1 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -422,6 +422,21 @@ relatively high IO latencies. With this set to 'true', git will do the index comparison to the filesystem data in parallel, allowing overlapping IO's. +core.notesRef:: + When showing commit messages, also show notes which are stored in + the given ref. This ref is expected to contain paths of the form + ??/*, where the directory name consists of the first two + characters of the commit name, and the base name consists of + the remaining 38 characters. ++ +If such a path exists in the given ref, the referenced blob is read, and +appended to the commit message, separated by a "Notes:" line. If the +given ref itself does not exist, it is not an error, but means that no +notes should be print. ++ +This setting defaults to "refs/notes/commits", and can be overridden by +the `GIT_NOTES_REF` environment variable. + alias.*:: Command aliases for the linkgit:git[1] command wrapper - e.g. after defining "alias.last = cat-file commit HEAD", the invocation diff --git a/Makefile b/Makefile index aabf0130b9..0bc96d8d32 100644 --- a/Makefile +++ b/Makefile @@ -370,6 +370,7 @@ LIB_H += ll-merge.h LIB_H += log-tree.h LIB_H += mailmap.h LIB_H += merge-recursive.h +LIB_H += notes.h LIB_H += object.h LIB_H += pack.h LIB_H += pack-refs.h @@ -451,6 +452,7 @@ LIB_OBJS += match-trees.o LIB_OBJS += merge-file.o LIB_OBJS += merge-recursive.o LIB_OBJS += name-hash.o +LIB_OBJS += notes.o LIB_OBJS += object.o LIB_OBJS += pack-check.o LIB_OBJS += pack-refs.o diff --git a/cache.h b/cache.h index 231c06d772..6158d5546b 100644 --- a/cache.h +++ b/cache.h @@ -367,6 +367,8 @@ static inline enum object_type object_type(unsigned int mode) #define GITATTRIBUTES_FILE ".gitattributes" #define INFOATTRIBUTES_FILE "info/attributes" #define ATTRIBUTE_MACRO_PREFIX "[attr]" +#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF" +#define GIT_NOTES_DEFAULT_REF "refs/notes/commits" extern int is_bare_repository_cfg; extern int is_bare_repository(void); @@ -538,6 +540,7 @@ enum rebase_setup_type { extern enum branch_track git_branch_track; extern enum rebase_setup_type autorebase; +extern char *notes_ref_name; #define GIT_REPO_VERSION 0 extern int repository_format_version; diff --git a/commit.c b/commit.c index c99db162a4..10e532afe1 100644 --- a/commit.c +++ b/commit.c @@ -5,6 +5,7 @@ #include "utf8.h" #include "diff.h" #include "revision.h" +#include "notes.h" int save_commit_buffer = 1; diff --git a/config.c b/config.c index 790405a213..e5d5b4bd06 100644 --- a/config.c +++ b/config.c @@ -469,6 +469,11 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.notesref")) { + notes_ref_name = xstrdup(value); + return 0; + } + if (!strcmp(var, "core.pager")) return git_config_string(&pager_program, var, value); diff --git a/environment.c b/environment.c index e278bce0ea..0edae21e74 100644 --- a/environment.c +++ b/environment.c @@ -45,6 +45,7 @@ enum rebase_setup_type autorebase = AUTOREBASE_NEVER; /* Parallel index stat data preload? */ int core_preload_index = 0; +char *notes_ref_name; /* This is set by setup_git_dir_gently() and/or git_default_config() */ char *git_work_tree_cfg; diff --git a/notes.c b/notes.c new file mode 100644 index 0000000000..91ec77f3f0 --- /dev/null +++ b/notes.c @@ -0,0 +1,68 @@ +#include "cache.h" +#include "commit.h" +#include "notes.h" +#include "refs.h" +#include "utf8.h" +#include "strbuf.h" + +static int initialized; + +void get_commit_notes(const struct commit *commit, struct strbuf *sb, + const char *output_encoding) +{ + static const char *utf8 = "utf-8"; + struct strbuf name = STRBUF_INIT; + const char *hex; + unsigned char sha1[20]; + char *msg; + unsigned long msgoffset, msglen; + enum object_type type; + + if (!initialized) { + const char *env = getenv(GIT_NOTES_REF_ENVIRONMENT); + if (env) + notes_ref_name = getenv(GIT_NOTES_REF_ENVIRONMENT); + else if (!notes_ref_name) + notes_ref_name = GIT_NOTES_DEFAULT_REF; + if (notes_ref_name && read_ref(notes_ref_name, sha1)) + notes_ref_name = NULL; + initialized = 1; + } + + if (!notes_ref_name) + return; + + strbuf_addf(&name, "%s:%s", notes_ref_name, + sha1_to_hex(commit->object.sha1)); + if (get_sha1(name.buf, sha1)) + return; + + if (!(msg = read_sha1_file(sha1, &type, &msglen)) || !msglen || + type != OBJ_BLOB) + return; + + if (output_encoding && *output_encoding && + strcmp(utf8, output_encoding)) { + char *reencoded = reencode_string(msg, output_encoding, utf8); + if (reencoded) { + free(msg); + msg = reencoded; + msglen = strlen(msg); + } + } + + /* we will end the annotation by a newline anyway */ + if (msglen && msg[msglen - 1] == '\n') + msglen--; + + strbuf_addstr(sb, "\nNotes:\n"); + + for (msgoffset = 0; msgoffset < msglen;) { + int linelen = strchrnul(msg, '\n') - msg; + + strbuf_addstr(sb, " "); + strbuf_add(sb, msg + msgoffset, linelen); + msgoffset += linelen; + } + free(msg); +} diff --git a/notes.h b/notes.h new file mode 100644 index 0000000000..79d21b65f5 --- /dev/null +++ b/notes.h @@ -0,0 +1,7 @@ +#ifndef NOTES_H +#define NOTES_H + +void get_commit_notes(const struct commit *commit, struct strbuf *sb, + const char *output_encoding); + +#endif diff --git a/pretty.c b/pretty.c index f6ff31264b..2d2872f3b5 100644 --- a/pretty.c +++ b/pretty.c @@ -6,6 +6,7 @@ #include "string-list.h" #include "mailmap.h" #include "log-tree.h" +#include "notes.h" static char *user_format; @@ -881,5 +882,9 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, */ if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) strbuf_addch(sb, '\n'); + + if (fmt != CMIT_FMT_ONELINE) + get_commit_notes(commit, sb, encoding); + free(reencoded); } -- cgit v1.2.3 From 7fcdb36e29f9a5e779bc9e44cd69f8f69fac9426 Mon Sep 17 00:00:00 2001 From: Jake Goulding Date: Mon, 26 Jan 2009 09:13:24 -0500 Subject: Make has_commit() non-static Move has_commit() from branch to a common location, in preparation for using it in "git-tag". Rename it to is_descendant_of() to make it more unique and descriptive. Signed-off-by: Jake Goulding Signed-off-by: Junio C Hamano --- builtin-branch.c | 20 +++----------------- commit.c | 15 +++++++++++++++ commit.h | 1 + 3 files changed, 19 insertions(+), 17 deletions(-) (limited to 'commit.c') diff --git a/builtin-branch.c b/builtin-branch.c index 82d6fb27c9..56a1971d69 100644 --- a/builtin-branch.c +++ b/builtin-branch.c @@ -193,21 +193,6 @@ struct ref_list { int kinds; }; -static int has_commit(struct commit *commit, struct commit_list *with_commit) -{ - if (!with_commit) - return 1; - while (with_commit) { - struct commit *other; - - other = with_commit->item; - with_commit = with_commit->next; - if (in_merge_bases(other, &commit, 1)) - return 1; - } - return 0; -} - static int append_ref(const char *refname, const unsigned char *sha1, int flags, void *cb_data) { struct ref_list *ref_list = (struct ref_list*)(cb_data); @@ -231,7 +216,7 @@ static int append_ref(const char *refname, const unsigned char *sha1, int flags, return error("branch '%s' does not point at a commit", refname); /* Filter with with_commit if specified */ - if (!has_commit(commit, ref_list->with_commit)) + if (!is_descendant_of(commit, ref_list->with_commit)) return 0; /* Don't add types the caller doesn't want */ @@ -401,7 +386,8 @@ static void print_ref_list(int kinds, int detached, int verbose, int abbrev, str qsort(ref_list.list, ref_list.index, sizeof(struct ref_item), ref_cmp); detached = (detached && (kinds & REF_LOCAL_BRANCH)); - if (detached && head_commit && has_commit(head_commit, with_commit)) { + if (detached && head_commit && + is_descendant_of(head_commit, with_commit)) { struct ref_item item; item.name = xstrdup("(no branch)"); item.kind = REF_LOCAL_BRANCH; diff --git a/commit.c b/commit.c index c99db162a4..aa3b35b6a8 100644 --- a/commit.c +++ b/commit.c @@ -705,6 +705,21 @@ struct commit_list *get_merge_bases(struct commit *one, struct commit *two, return get_merge_bases_many(one, 1, &two, cleanup); } +int is_descendant_of(struct commit *commit, struct commit_list *with_commit) +{ + if (!with_commit) + return 1; + while (with_commit) { + struct commit *other; + + other = with_commit->item; + with_commit = with_commit->next; + if (in_merge_bases(other, &commit, 1)) + return 1; + } + return 0; +} + int in_merge_bases(struct commit *commit, struct commit **reference, int num) { struct commit_list *bases, *b; diff --git a/commit.h b/commit.h index 3a7b06a828..ba9f63813e 100644 --- a/commit.h +++ b/commit.h @@ -133,6 +133,7 @@ extern int is_repository_shallow(void); extern struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); +int is_descendant_of(struct commit *, struct commit_list *); int in_merge_bases(struct commit *, struct commit **, int); extern int interactive_add(int argc, const char **argv, const char *prefix); -- cgit v1.2.3 From 954cfb5cfd17d57b9b31b19b73efe73199407e07 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Tue, 10 Feb 2009 21:31:33 -0800 Subject: Revert "Merge branch 'js/notes'" This reverts commit 7b75b331f6744fbf953fe8913703378ef86a2189, reversing changes made to 5d680a67d7909c89af96eba4a2d77abed606292b. --- .gitignore | 1 - Documentation/RelNotes-1.6.2.txt | 2 - Documentation/config.txt | 13 ---- Documentation/git-notes.txt | 46 ----------- Makefile | 3 - cache.h | 3 - command-list.txt | 1 - commit.c | 1 - config.c | 5 -- environment.c | 1 - git-notes.sh | 65 ---------------- notes.c | 160 --------------------------------------- notes.h | 7 -- pretty.c | 5 -- t/t3301-notes.sh | 95 ----------------------- t/t3302-notes-index-expensive.sh | 98 ------------------------ 16 files changed, 506 deletions(-) delete mode 100644 Documentation/git-notes.txt delete mode 100755 git-notes.sh delete mode 100644 notes.c delete mode 100644 notes.h delete mode 100755 t/t3301-notes.sh delete mode 100755 t/t3302-notes-index-expensive.sh (limited to 'commit.c') diff --git a/.gitignore b/.gitignore index 13311f1d5e..1c57d4c958 100644 --- a/.gitignore +++ b/.gitignore @@ -82,7 +82,6 @@ git-mktag git-mktree git-name-rev git-mv -git-notes git-pack-redundant git-pack-objects git-pack-refs diff --git a/Documentation/RelNotes-1.6.2.txt b/Documentation/RelNotes-1.6.2.txt index f1bfa82749..b86b684d23 100644 --- a/Documentation/RelNotes-1.6.2.txt +++ b/Documentation/RelNotes-1.6.2.txt @@ -37,8 +37,6 @@ Updates since v1.6.1 * automatic typo correction works on aliases as well -* Initial support for "git notes" implemented. - * @{-1} is a way to refer to the last branch you were on. This is accepted not only where an object name is expected, but anywhere a branch name is expected. E.g. "git branch --track mybranch @{-1}" diff --git a/Documentation/config.txt b/Documentation/config.txt index 1dd18c928d..1806a60610 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -422,19 +422,6 @@ relatively high IO latencies. With this set to 'true', git will do the index comparison to the filesystem data in parallel, allowing overlapping IO's. -core.notesRef:: - When showing commit messages, also show notes which are stored in - the given ref. This ref is expected to contain files named - after the full SHA-1 of the commit they annotate. -+ -If such a file exists in the given ref, the referenced blob is read, and -appended to the commit message, separated by a "Notes:" line. If the -given ref itself does not exist, it is not an error, but means that no -notes should be printed. -+ -This setting defaults to "refs/notes/commits", and can be overridden by -the `GIT_NOTES_REF` environment variable. - alias.*:: Command aliases for the linkgit:git[1] command wrapper - e.g. after defining "alias.last = cat-file commit HEAD", the invocation diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt deleted file mode 100644 index 3d93625f9a..0000000000 --- a/Documentation/git-notes.txt +++ /dev/null @@ -1,46 +0,0 @@ -git-notes(1) -============ - -NAME ----- -git-notes - Add/inspect commit notes - -SYNOPSIS --------- -[verse] -'git-notes' (edit | show) [commit] - -DESCRIPTION ------------ -This command allows you to add notes to commit messages, without -changing the commit. To discern these notes from the message stored -in the commit object, the notes are indented like the message, after -an unindented line saying "Notes:". - -To disable commit notes, you have to set the config variable -core.notesRef to the empty string. Alternatively, you can set it -to a different ref, something like "refs/notes/bugzilla". This setting -can be overridden by the environment variable "GIT_NOTES_REF". - - -SUBCOMMANDS ------------ - -edit:: - Edit the notes for a given commit (defaults to HEAD). - -show:: - Show the notes for a given commit (defaults to HEAD). - - -Author ------- -Written by Johannes Schindelin - -Documentation -------------- -Documentation by Johannes Schindelin - -GIT ---- -Part of the gitlink:git[7] suite diff --git a/Makefile b/Makefile index 27b9569746..627d4d09ba 100644 --- a/Makefile +++ b/Makefile @@ -265,7 +265,6 @@ SCRIPT_SH += git-merge-octopus.sh 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-parse-remote.sh SCRIPT_SH += git-pull.sh SCRIPT_SH += git-quiltimport.sh @@ -378,7 +377,6 @@ LIB_H += ll-merge.h LIB_H += log-tree.h LIB_H += mailmap.h LIB_H += merge-recursive.h -LIB_H += notes.h LIB_H += object.h LIB_H += pack.h LIB_H += pack-refs.h @@ -461,7 +459,6 @@ LIB_OBJS += match-trees.o LIB_OBJS += merge-file.o LIB_OBJS += merge-recursive.o LIB_OBJS += name-hash.o -LIB_OBJS += notes.o LIB_OBJS += object.o LIB_OBJS += pack-check.o LIB_OBJS += pack-refs.o diff --git a/cache.h b/cache.h index 7f1a6e8bd0..a7f435ddef 100644 --- a/cache.h +++ b/cache.h @@ -371,8 +371,6 @@ static inline enum object_type object_type(unsigned int mode) #define GITATTRIBUTES_FILE ".gitattributes" #define INFOATTRIBUTES_FILE "info/attributes" #define ATTRIBUTE_MACRO_PREFIX "[attr]" -#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF" -#define GIT_NOTES_DEFAULT_REF "refs/notes/commits" extern int is_bare_repository_cfg; extern int is_bare_repository(void); @@ -544,7 +542,6 @@ enum rebase_setup_type { extern enum branch_track git_branch_track; extern enum rebase_setup_type autorebase; -extern char *notes_ref_name; #define GIT_REPO_VERSION 0 extern int repository_format_version; diff --git a/command-list.txt b/command-list.txt index 2dc2c3320c..3583a33ee9 100644 --- a/command-list.txt +++ b/command-list.txt @@ -73,7 +73,6 @@ git-mktag plumbingmanipulators git-mktree plumbingmanipulators git-mv mainporcelain common git-name-rev plumbinginterrogators -git-notes mainporcelain git-pack-objects plumbingmanipulators git-pack-redundant plumbinginterrogators git-pack-refs ancillarymanipulators diff --git a/commit.c b/commit.c index cf72143f58..aa3b35b6a8 100644 --- a/commit.c +++ b/commit.c @@ -5,7 +5,6 @@ #include "utf8.h" #include "diff.h" #include "revision.h" -#include "notes.h" int save_commit_buffer = 1; diff --git a/config.c b/config.c index e5d5b4bd06..790405a213 100644 --- a/config.c +++ b/config.c @@ -469,11 +469,6 @@ static int git_default_core_config(const char *var, const char *value) return 0; } - if (!strcmp(var, "core.notesref")) { - notes_ref_name = xstrdup(value); - return 0; - } - if (!strcmp(var, "core.pager")) return git_config_string(&pager_program, var, value); diff --git a/environment.c b/environment.c index 0edae21e74..e278bce0ea 100644 --- a/environment.c +++ b/environment.c @@ -45,7 +45,6 @@ enum rebase_setup_type autorebase = AUTOREBASE_NEVER; /* Parallel index stat data preload? */ int core_preload_index = 0; -char *notes_ref_name; /* This is set by setup_git_dir_gently() and/or git_default_config() */ char *git_work_tree_cfg; diff --git a/git-notes.sh b/git-notes.sh deleted file mode 100755 index bfdbaa8527..0000000000 --- a/git-notes.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/sh - -USAGE="(edit | show) [commit]" -. git-sh-setup - -test -n "$3" && usage - -test -z "$1" && usage -ACTION="$1"; shift - -test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="$(git config core.notesref)" -test -z "$GIT_NOTES_REF" && GIT_NOTES_REF="refs/notes/commits" - -COMMIT=$(git rev-parse --verify --default HEAD "$@") || -die "Invalid commit: $@" - -MESSAGE="$GIT_DIR"/new-notes-$COMMIT -trap ' - test -f "$MESSAGE" && rm "$MESSAGE" -' 0 - -case "$ACTION" in -edit) - GIT_NOTES_REF= git log -1 $COMMIT | sed "s/^/#/" > "$MESSAGE" - - GIT_INDEX_FILE="$MESSAGE".idx - export GIT_INDEX_FILE - - CURRENT_HEAD=$(git show-ref "$GIT_NOTES_REF" | cut -f 1 -d ' ') - if [ -z "$CURRENT_HEAD" ]; then - PARENT= - else - PARENT="-p $CURRENT_HEAD" - git read-tree "$GIT_NOTES_REF" || die "Could not read index" - git cat-file blob :$COMMIT >> "$MESSAGE" 2> /dev/null - fi - - ${VISUAL:-${EDITOR:-vi}} "$MESSAGE" - - grep -v ^# < "$MESSAGE" | git stripspace > "$MESSAGE".processed - mv "$MESSAGE".processed "$MESSAGE" - if [ -s "$MESSAGE" ]; then - BLOB=$(git hash-object -w "$MESSAGE") || - die "Could not write into object database" - git update-index --add --cacheinfo 0644 $BLOB $COMMIT || - die "Could not write index" - else - test -z "$CURRENT_HEAD" && - die "Will not initialise with empty tree" - git update-index --force-remove $COMMIT || - die "Could not update index" - fi - - TREE=$(git write-tree) || die "Could not write tree" - NEW_HEAD=$(echo Annotate $COMMIT | git commit-tree $TREE $PARENT) || - die "Could not annotate" - git update-ref -m "Annotate $COMMIT" \ - "$GIT_NOTES_REF" $NEW_HEAD $CURRENT_HEAD -;; -show) - git show "$GIT_NOTES_REF":$COMMIT -;; -*) - usage -esac diff --git a/notes.c b/notes.c deleted file mode 100644 index bd737842d9..0000000000 --- a/notes.c +++ /dev/null @@ -1,160 +0,0 @@ -#include "cache.h" -#include "commit.h" -#include "notes.h" -#include "refs.h" -#include "utf8.h" -#include "strbuf.h" -#include "tree-walk.h" - -struct entry { - unsigned char commit_sha1[20]; - unsigned char notes_sha1[20]; -}; - -struct hash_map { - struct entry *entries; - off_t count, size; -}; - -static int initialized; -static struct hash_map hash_map; - -static int hash_index(struct hash_map *map, const unsigned char *sha1) -{ - int i = ((*(unsigned int *)sha1) % map->size); - - for (;;) { - unsigned char *current = map->entries[i].commit_sha1; - - if (!hashcmp(sha1, current)) - return i; - - if (is_null_sha1(current)) - return -1 - i; - - if (++i == map->size) - i = 0; - } -} - -static void add_entry(const unsigned char *commit_sha1, - const unsigned char *notes_sha1) -{ - int index; - - if (hash_map.count + 1 > hash_map.size >> 1) { - int i, old_size = hash_map.size; - struct entry *old = hash_map.entries; - - hash_map.size = old_size ? old_size << 1 : 64; - hash_map.entries = (struct entry *) - xcalloc(sizeof(struct entry), hash_map.size); - - for (i = 0; i < old_size; i++) - if (!is_null_sha1(old[i].commit_sha1)) { - index = -1 - hash_index(&hash_map, - old[i].commit_sha1); - memcpy(hash_map.entries + index, old + i, - sizeof(struct entry)); - } - free(old); - } - - index = hash_index(&hash_map, commit_sha1); - if (index < 0) { - index = -1 - index; - hash_map.count++; - } - - hashcpy(hash_map.entries[index].commit_sha1, commit_sha1); - hashcpy(hash_map.entries[index].notes_sha1, notes_sha1); -} - -static void initialize_hash_map(const char *notes_ref_name) -{ - unsigned char sha1[20], commit_sha1[20]; - unsigned mode; - struct tree_desc desc; - struct name_entry entry; - void *buf; - - if (!notes_ref_name || read_ref(notes_ref_name, commit_sha1) || - get_tree_entry(commit_sha1, "", sha1, &mode)) - return; - - buf = fill_tree_descriptor(&desc, sha1); - if (!buf) - die("Could not read %s for notes-index", sha1_to_hex(sha1)); - - while (tree_entry(&desc, &entry)) - if (!get_sha1(entry.path, commit_sha1)) - add_entry(commit_sha1, entry.sha1); - free(buf); -} - -static unsigned char *lookup_notes(const unsigned char *commit_sha1) -{ - int index; - - if (!hash_map.size) - return NULL; - - index = hash_index(&hash_map, commit_sha1); - if (index < 0) - return NULL; - return hash_map.entries[index].notes_sha1; -} - -void get_commit_notes(const struct commit *commit, struct strbuf *sb, - const char *output_encoding) -{ - static const char *utf8 = "utf-8"; - unsigned char *sha1; - char *msg, *msg_p; - unsigned long linelen, msglen; - enum object_type type; - - if (!initialized) { - const char *env = getenv(GIT_NOTES_REF_ENVIRONMENT); - if (env) - notes_ref_name = getenv(GIT_NOTES_REF_ENVIRONMENT); - else if (!notes_ref_name) - notes_ref_name = GIT_NOTES_DEFAULT_REF; - initialize_hash_map(notes_ref_name); - initialized = 1; - } - - sha1 = lookup_notes(commit->object.sha1); - if (!sha1) - return; - - if (!(msg = read_sha1_file(sha1, &type, &msglen)) || !msglen || - type != OBJ_BLOB) - return; - - if (output_encoding && *output_encoding && - strcmp(utf8, output_encoding)) { - char *reencoded = reencode_string(msg, output_encoding, utf8); - if (reencoded) { - free(msg); - msg = reencoded; - msglen = strlen(msg); - } - } - - /* we will end the annotation by a newline anyway */ - if (msglen && msg[msglen - 1] == '\n') - msglen--; - - strbuf_addstr(sb, "\nNotes:\n"); - - for (msg_p = msg; msg_p < msg + msglen; msg_p += linelen + 1) { - linelen = strchrnul(msg_p, '\n') - msg_p; - - strbuf_addstr(sb, " "); - strbuf_add(sb, msg_p, linelen); - strbuf_addch(sb, '\n'); - } - - free(msg); -} diff --git a/notes.h b/notes.h deleted file mode 100644 index 79d21b65f5..0000000000 --- a/notes.h +++ /dev/null @@ -1,7 +0,0 @@ -#ifndef NOTES_H -#define NOTES_H - -void get_commit_notes(const struct commit *commit, struct strbuf *sb, - const char *output_encoding); - -#endif diff --git a/pretty.c b/pretty.c index 8d4dbc9fbb..cc460b5697 100644 --- a/pretty.c +++ b/pretty.c @@ -6,7 +6,6 @@ #include "string-list.h" #include "mailmap.h" #include "log-tree.h" -#include "notes.h" #include "color.h" static char *user_format; @@ -921,9 +920,5 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, */ if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) strbuf_addch(sb, '\n'); - - if (fmt != CMIT_FMT_ONELINE) - get_commit_notes(commit, sb, encoding); - free(reencoded); } diff --git a/t/t3301-notes.sh b/t/t3301-notes.sh deleted file mode 100755 index 9393a25511..0000000000 --- a/t/t3301-notes.sh +++ /dev/null @@ -1,95 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2007 Johannes E. Schindelin -# - -test_description='Test commit notes' - -. ./test-lib.sh - -cat > fake_editor.sh << \EOF -echo "$MSG" > "$1" -echo "$MSG" >& 2 -EOF -chmod a+x fake_editor.sh -VISUAL=./fake_editor.sh -export VISUAL - -test_expect_success 'cannot annotate non-existing HEAD' ' - ! MSG=3 git notes edit -' - -test_expect_success setup ' - : > a1 && - git add a1 && - test_tick && - git commit -m 1st && - : > a2 && - git add a2 && - test_tick && - git commit -m 2nd -' - -test_expect_success 'need valid notes ref' ' - ! MSG=1 GIT_NOTES_REF='/' git notes edit && - ! MSG=2 GIT_NOTES_REF='/' git notes show -' - -test_expect_success 'create notes' ' - git config core.notesRef refs/notes/commits && - MSG=b1 git notes edit && - test ! -f .git/new-notes && - test 1 = $(git ls-tree refs/notes/commits | wc -l) && - test b1 = $(git notes show) && - git show HEAD^ && - ! git notes show HEAD^ -' - -cat > expect << EOF -commit 268048bfb8a1fb38e703baceb8ab235421bf80c5 -Author: A U Thor -Date: Thu Apr 7 15:14:13 2005 -0700 - - 2nd - -Notes: - b1 -EOF - -test_expect_success 'show notes' ' - ! (git cat-file commit HEAD | grep b1) && - git log -1 > output && - test_cmp expect output -' -test_expect_success 'create multi-line notes (setup)' ' - : > a3 && - git add a3 && - test_tick && - git commit -m 3rd && - MSG="b3 -c3c3c3c3 -d3d3d3" git notes edit -' - -cat > expect-multiline << EOF -commit 1584215f1d29c65e99c6c6848626553fdd07fd75 -Author: A U Thor -Date: Thu Apr 7 15:15:13 2005 -0700 - - 3rd - -Notes: - b3 - c3c3c3c3 - d3d3d3 -EOF - -printf "\n" >> expect-multiline -cat expect >> expect-multiline - -test_expect_success 'show multi-line notes' ' - git log -2 > output && - test_cmp expect-multiline output -' - -test_done diff --git a/t/t3302-notes-index-expensive.sh b/t/t3302-notes-index-expensive.sh deleted file mode 100755 index 00d27bf6ef..0000000000 --- a/t/t3302-notes-index-expensive.sh +++ /dev/null @@ -1,98 +0,0 @@ -#!/bin/sh -# -# Copyright (c) 2007 Johannes E. Schindelin -# - -test_description='Test commit notes index (expensive!)' - -. ./test-lib.sh - -test -z "$GIT_NOTES_TIMING_TESTS" && { - say Skipping timing tests - test_done - exit -} - -create_repo () { - number_of_commits=$1 - nr=0 - parent= - test -d .git || { - git init && - tree=$(git write-tree) && - while [ $nr -lt $number_of_commits ]; do - test_tick && - commit=$(echo $nr | git commit-tree $tree $parent) || - return - parent="-p $commit" - nr=$(($nr+1)) - done && - git update-ref refs/heads/master $commit && - { - export GIT_INDEX_FILE=.git/temp; - git rev-list HEAD | cat -n | sed "s/^[ ][ ]*/ /g" | - while read nr sha1; do - blob=$(echo note $nr | git hash-object -w --stdin) && - echo $sha1 | sed "s/^/0644 $blob 0 /" - done | git update-index --index-info && - tree=$(git write-tree) && - test_tick && - commit=$(echo notes | git commit-tree $tree) && - git update-ref refs/notes/commits $commit - } && - git config core.notesRef refs/notes/commits - } -} - -test_notes () { - count=$1 && - git config core.notesRef refs/notes/commits && - git log | grep "^ " > output && - i=1 && - while [ $i -le $count ]; do - echo " $(($count-$i))" && - echo " note $i" && - i=$(($i+1)); - done > expect && - git diff expect output -} - -cat > time_notes << \EOF - mode=$1 - i=1 - while [ $i -lt $2 ]; do - case $1 in - no-notes) - export GIT_NOTES_REF=non-existing - ;; - notes) - unset GIT_NOTES_REF - ;; - esac - git log >/dev/null - i=$(($i+1)) - done -EOF - -time_notes () { - for mode in no-notes notes - do - echo $mode - /usr/bin/time sh ../time_notes $mode $1 - done -} - -for count in 10 100 1000 10000; do - - mkdir $count - (cd $count; - - test_expect_success "setup $count" "create_repo $count" - - test_expect_success 'notes work' "test_notes $count" - - test_expect_success 'notes timing' "time_notes 100" - ) -done - -test_done -- cgit v1.2.3 From 836a3fd5b0c439642268fd1299cd16729f15e614 Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Sun, 17 May 2009 17:36:45 +0200 Subject: commit: add function to unparse a commit and its parents This patch adds the "unparse_commit" function that returns a commit into an unparsed state by freeing its data and resetting its fields to 0. Its parents are recursively unparsed too, because they might have been changed. But its tree is not unparsed as it should not have been modifed. Note that as the "flags" and "used" fields may be used even if the object is not parsed, we have to reset them anyway. Signed-off-by: Christian Couder Signed-off-by: Junio C Hamano --- commit.c | 20 ++++++++++++++++++++ commit.h | 2 ++ 2 files changed, 22 insertions(+) (limited to 'commit.c') diff --git a/commit.c b/commit.c index aa3b35b6a8..8f6b703c55 100644 --- a/commit.c +++ b/commit.c @@ -316,6 +316,26 @@ int parse_commit(struct commit *item) return ret; } +static void unparse_commit_list(struct commit_list *list) +{ + for (; list; list = list->next) + unparse_commit(list->item); +} + +void unparse_commit(struct commit *item) +{ + item->object.flags = 0; + item->object.used = 0; + if (item->object.parsed) { + item->object.parsed = 0; + if (item->parents) { + unparse_commit_list(item->parents); + free_commit_list(item->parents); + item->parents = NULL; + } + } +} + struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p) { struct commit_list *new_list = xmalloc(sizeof(struct commit_list)); diff --git a/commit.h b/commit.h index ba9f63813e..f3eaf1d048 100644 --- a/commit.h +++ b/commit.h @@ -40,6 +40,8 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size); int parse_commit(struct commit *item); +void unparse_commit(struct commit *item); + struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p); unsigned commit_list_count(const struct commit_list *l); struct commit_list * insert_by_date(struct commit *item, struct commit_list **list); -- cgit v1.2.3 From 7a8e3895f68e9ae4e44e521c78fc98768c2a88ec Mon Sep 17 00:00:00 2001 From: Christian Couder Date: Wed, 27 May 2009 07:09:40 +0200 Subject: bisect: drop unparse_commit() and use clear_commit_marks() The goal of this patch series is to check if good revisions are ancestor of the bad revision without forking a process to launch "git rev-list $good ^$bad". This new version of this patch series does not use an "unparse_commit" function anymore, we use "clear_commit_marks" instead. Signed-off-by: Junio C Hamano --- bisect.c | 2 +- commit.c | 20 -------------------- commit.h | 2 -- 3 files changed, 1 insertion(+), 23 deletions(-) (limited to 'commit.c') diff --git a/bisect.c b/bisect.c index c43c120bde..18f9fa4062 100644 --- a/bisect.c +++ b/bisect.c @@ -771,7 +771,7 @@ static int check_ancestors(const char *prefix) /* Clean up objects used, as they will be reused. */ for (i = 0; i < pending_copy.nr; i++) { struct object *o = pending_copy.objects[i].item; - unparse_commit((struct commit *)o); + clear_commit_marks((struct commit *)o, ALL_REV_FLAGS); } return res; diff --git a/commit.c b/commit.c index 8f6b703c55..aa3b35b6a8 100644 --- a/commit.c +++ b/commit.c @@ -316,26 +316,6 @@ int parse_commit(struct commit *item) return ret; } -static void unparse_commit_list(struct commit_list *list) -{ - for (; list; list = list->next) - unparse_commit(list->item); -} - -void unparse_commit(struct commit *item) -{ - item->object.flags = 0; - item->object.used = 0; - if (item->object.parsed) { - item->object.parsed = 0; - if (item->parents) { - unparse_commit_list(item->parents); - free_commit_list(item->parents); - item->parents = NULL; - } - } -} - struct commit_list *commit_list_insert(struct commit *item, struct commit_list **list_p) { struct commit_list *new_list = xmalloc(sizeof(struct commit_list)); diff --git a/commit.h b/commit.h index f3eaf1d048..ba9f63813e 100644 --- a/commit.h +++ b/commit.h @@ -40,8 +40,6 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size); int parse_commit(struct commit *item); -void unparse_commit(struct commit *item); - struct commit_list * commit_list_insert(struct commit *item, struct commit_list **list_p); unsigned commit_list_count(const struct commit_list *l); struct commit_list * insert_by_date(struct commit *item, struct commit_list **list); -- cgit v1.2.3 From f290974390c9be76e9166df6f0ab5ad790b812ac Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Thu, 2 Jul 2009 21:34:54 -0700 Subject: Allow the Unix epoch to be a valid commit date It is common practice to use the Unix epoch as a fallback date when a suitable date is not available. This is true of git svn and possibly other importing tools that import non-git history into git. Instead of clobbering established strtoul() error reporting semantics with our own, preserve the strtoul() error value of ULONG_MAX for fsck.c to handle. Signed-off-by: Eric Wong Signed-off-by: Junio C Hamano --- commit.c | 6 +----- fsck.c | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index aa3b35b6a8..a47fb4da27 100644 --- a/commit.c +++ b/commit.c @@ -50,7 +50,6 @@ struct commit *lookup_commit(const unsigned char *sha1) static unsigned long parse_commit_date(const char *buf, const char *tail) { - unsigned long date; const char *dateptr; if (buf + 6 >= tail) @@ -73,10 +72,7 @@ static unsigned long parse_commit_date(const char *buf, const char *tail) if (buf >= tail) return 0; /* dateptr < buf && buf[-1] == '\n', so strtoul will stop at buf-1 */ - date = strtoul(dateptr, NULL, 10); - if (date == ULONG_MAX) - date = 0; - return date; + return strtoul(dateptr, NULL, 10); } static struct commit_graft **commit_graft; diff --git a/fsck.c b/fsck.c index 511b82cba9..89278c1459 100644 --- a/fsck.c +++ b/fsck.c @@ -229,7 +229,7 @@ static int fsck_commit(struct commit *commit, fsck_error error_func) struct commit_graft *graft; int parents = 0; - if (!commit->date) + if (commit->date == ULONG_MAX) return error_func(&commit->object, FSCK_ERROR, "invalid author/committer line"); if (memcmp(buffer, "tree ", 5)) -- cgit v1.2.3 From 7f3140cd23f126e578ccaaea8c2cebe36824a7ac Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Thu, 23 Jul 2009 17:33:49 +0200 Subject: git repack: keep commits hidden by a graft When you have grafts that pretend that a given commit has different parents than the ones recorded in the commit object, it is dangerous to let 'git repack' remove those hidden parents, as you can easily remove the graft and end up with a broken repository. So let's play it safe and keep those parent objects and everything that is reachable by them, in addition to the grafted parents. As this behavior can only be triggered by git pack-objects, and as that command handles duplicate parents gracefully, we do not bother to cull duplicated parents that may result by using both true and grafted parents. Signed-off-by: Johannes Schindelin Signed-off-by: Junio C Hamano --- Documentation/git-pack-objects.txt | 7 ++++++- builtin-pack-objects.c | 4 ++++ cache.h | 2 ++ commit.c | 6 +++++- environment.c | 1 + git-repack.sh | 2 +- t/t7700-repack.sh | 2 +- 7 files changed, 20 insertions(+), 4 deletions(-) (limited to 'commit.c') diff --git a/Documentation/git-pack-objects.txt b/Documentation/git-pack-objects.txt index 7d4c1a7556..2e4992970e 100644 --- a/Documentation/git-pack-objects.txt +++ b/Documentation/git-pack-objects.txt @@ -11,7 +11,8 @@ SYNOPSIS [verse] 'git pack-objects' [-q] [--no-reuse-delta] [--delta-base-offset] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] [--all-progress] - [--revs [--unpacked | --all]*] [--stdout | base-name] < object-list + [--revs [--unpacked | --all]*] [--stdout | base-name] + [--keep-true-parents] < object-list DESCRIPTION @@ -197,6 +198,10 @@ base-name:: to force the version for the generated pack index, and to force 64-bit index entries on objects located above the given offset. +--keep-true-parents:: + With this option, parents that are hidden by grafts are packed + nevertheless. + Author ------ diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index 941cc2d73c..527638168b 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -2259,6 +2259,10 @@ int cmd_pack_objects(int argc, const char **argv, const char *prefix) die("bad %s", arg); continue; } + if (!strcmp(arg, "--keep-true-parents")) { + grafts_replace_parents = 0; + continue; + } usage(pack_usage); } diff --git a/cache.h b/cache.h index b8503ad91c..e902008297 100644 --- a/cache.h +++ b/cache.h @@ -561,6 +561,8 @@ enum object_creation_mode { extern enum object_creation_mode object_creation_mode; +extern int grafts_replace_parents; + #define GIT_REPO_VERSION 0 extern int repository_format_version; extern int check_repository_format(void); diff --git a/commit.c b/commit.c index aa3b35b6a8..f69525a089 100644 --- a/commit.c +++ b/commit.c @@ -266,7 +266,11 @@ int parse_commit_buffer(struct commit *item, void *buffer, unsigned long size) bufptr[47] != '\n') return error("bad parents in commit %s", sha1_to_hex(item->object.sha1)); bufptr += 48; - if (graft) + /* + * The clone is shallow if nr_parent < 0, and we must + * not traverse its real parents even when we unhide them. + */ + if (graft && (graft->nr_parent < 0 || grafts_replace_parents)) continue; new_parent = lookup_commit(parent); if (new_parent) diff --git a/environment.c b/environment.c index 801a005ef1..477d2e4da8 100644 --- a/environment.c +++ b/environment.c @@ -47,6 +47,7 @@ enum push_default_type push_default = PUSH_DEFAULT_UNSPECIFIED; #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS #endif enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE; +int grafts_replace_parents = 1; /* Parallel index stat data preload? */ int core_preload_index = 0; diff --git a/git-repack.sh b/git-repack.sh index 0868734723..be0c8435dc 100755 --- a/git-repack.sh +++ b/git-repack.sh @@ -81,7 +81,7 @@ case ",$all_into_one," in esac args="$args $local $quiet $no_reuse$extra" -names=$(git pack-objects --honor-pack-keep --non-empty --all --reflog $args Date: Thu, 27 Aug 2009 11:16:34 -0500 Subject: commit.c: rename variable named 'n' which masks previous declaration The variable named 'n' was initially declared to be of type int. The name 'n' was reused inside inner blocks as a different type. Rename the uses within inner blocks to avoid confusion and give them a slightly more descriptive name. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- commit.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index e2bcbe8149..a6c6f70a92 100644 --- a/commit.c +++ b/commit.c @@ -564,13 +564,13 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co while (interesting(list)) { struct commit *commit; struct commit_list *parents; - struct commit_list *n; + struct commit_list *next; int flags; commit = list->item; - n = list->next; + next = list->next; free(list); - list = n; + list = next; flags = commit->object.flags & (PARENT1 | PARENT2 | STALE); if (flags == (PARENT1 | PARENT2)) { @@ -598,11 +598,11 @@ static struct commit_list *merge_bases_many(struct commit *one, int n, struct co free_commit_list(list); list = result; result = NULL; while (list) { - struct commit_list *n = list->next; + struct commit_list *next = list->next; if (!(list->item->object.flags & STALE)) insert_by_date(list->item, &result); free(list); - list = n; + list = next; } return result; } -- cgit v1.2.3 From 2b7ca830c6a6e4f0e1722e24973a026b5b867227 Mon Sep 17 00:00:00 2001 From: Jim Meyering Date: Sat, 12 Sep 2009 10:54:32 +0200 Subject: use write_str_in_full helper to avoid literal string lengths In 2d14d65 (Use a clearer style to issue commands to remote helpers, 2009-09-03) I happened to notice two changes like this: - write_in_full(helper->in, "list\n", 5); + + strbuf_addstr(&buf, "list\n"); + write_in_full(helper->in, buf.buf, buf.len); + strbuf_reset(&buf); IMHO, it would be better to define a new function, static inline ssize_t write_str_in_full(int fd, const char *str) { return write_in_full(fd, str, strlen(str)); } and then use it like this: - strbuf_addstr(&buf, "list\n"); - write_in_full(helper->in, buf.buf, buf.len); - strbuf_reset(&buf); + write_str_in_full(helper->in, "list\n"); Thus not requiring the added allocation, and still avoiding the maintenance risk of literal string lengths. These days, compilers are good enough that strlen("literal") imposes no run-time cost. Transformed via this: perl -pi -e \ 's/write_in_full\((.*?), (".*?"), \d+\)/write_str_in_full($1, $2)/'\ $(git grep -l 'write_in_full.*"') Signed-off-by: Jim Meyering Signed-off-by: Junio C Hamano --- builtin-fetch.c | 2 +- builtin-reflog.c | 2 +- cache.h | 9 +++++++-- commit.c | 2 +- config.c | 2 +- rerere.c | 2 +- upload-pack.c | 4 ++-- 7 files changed, 14 insertions(+), 9 deletions(-) (limited to 'commit.c') diff --git a/builtin-fetch.c b/builtin-fetch.c index 817dd6bff0..cb48c57ca3 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -454,7 +454,7 @@ static int quickfetch(struct ref *ref_map) for (ref = ref_map; ref; ref = ref->next) { if (write_in_full(revlist.in, sha1_to_hex(ref->old_sha1), 40) < 0 || - write_in_full(revlist.in, "\n", 1) < 0) { + write_str_in_full(revlist.in, "\n") < 0) { if (errno != EPIPE && errno != EINVAL) error("failed write to rev-list: %s", strerror(errno)); err = -1; diff --git a/builtin-reflog.c b/builtin-reflog.c index 95198c5de4..e23b5ef979 100644 --- a/builtin-reflog.c +++ b/builtin-reflog.c @@ -362,7 +362,7 @@ static int expire_reflog(const char *ref, const unsigned char *sha1, int unused, } else if (cmd->updateref && (write_in_full(lock->lock_fd, sha1_to_hex(cb.last_kept_sha1), 40) != 40 || - write_in_full(lock->lock_fd, "\n", 1) != 1 || + write_str_in_full(lock->lock_fd, "\n") != 1 || close_ref(lock) < 0)) { status |= error("Couldn't write %s", lock->lk->filename); diff --git a/cache.h b/cache.h index 5fad24ce21..867918d041 100644 --- a/cache.h +++ b/cache.h @@ -923,13 +923,18 @@ extern const char *git_mailmap_file; extern void maybe_flush_or_die(FILE *, const char *); extern int copy_fd(int ifd, int ofd); extern int copy_file(const char *dst, const char *src, int mode); -extern ssize_t read_in_full(int fd, void *buf, size_t count); -extern ssize_t write_in_full(int fd, const void *buf, size_t count); extern void write_or_die(int fd, const void *buf, size_t count); extern int write_or_whine(int fd, const void *buf, size_t count, const char *msg); extern int write_or_whine_pipe(int fd, const void *buf, size_t count, const char *msg); extern void fsync_or_die(int fd, const char *); +extern ssize_t read_in_full(int fd, void *buf, size_t count); +extern ssize_t write_in_full(int fd, const void *buf, size_t count); +static inline ssize_t write_str_in_full(int fd, const char *str) +{ + return write_in_full(fd, str, strlen(str)); +} + /* pager.c */ extern void setup_pager(void); extern const char *pager_program; diff --git a/commit.c b/commit.c index a6c6f70a92..fedbd5e526 100644 --- a/commit.c +++ b/commit.c @@ -212,7 +212,7 @@ int write_shallow_commits(int fd, int use_pack_protocol) else { if (write_in_full(fd, hex, 40) != 40) break; - if (write_in_full(fd, "\n", 1) != 1) + if (write_str_in_full(fd, "\n") != 1) break; } } diff --git a/config.c b/config.c index e87edeab0c..bf122202a0 100644 --- a/config.c +++ b/config.c @@ -1116,7 +1116,7 @@ int git_config_set_multivar(const char *key, const char *value, copy_end - copy_begin) goto write_err_out; if (new_line && - write_in_full(fd, "\n", 1) != 1) + write_str_in_full(fd, "\n") != 1) goto write_err_out; } copy_begin = store.offset[i]; diff --git a/rerere.c b/rerere.c index 87360dc23e..29f95f657d 100644 --- a/rerere.c +++ b/rerere.c @@ -61,7 +61,7 @@ static int write_rr(struct string_list *rr, int out_fd) path = rr->items[i].string; length = strlen(path) + 1; if (write_in_full(out_fd, rr->items[i].util, 40) != 40 || - write_in_full(out_fd, "\t", 1) != 1 || + write_str_in_full(out_fd, "\t") != 1 || write_in_full(out_fd, path, length) != length) die("unable to write rerere record"); } diff --git a/upload-pack.c b/upload-pack.c index c77ab710c4..b3471e417d 100644 --- a/upload-pack.c +++ b/upload-pack.c @@ -553,7 +553,7 @@ static void receive_needs(void) shallow_nr = 0; if (debug_fd) - write_in_full(debug_fd, "#S\n", 3); + write_str_in_full(debug_fd, "#S\n"); for (;;) { struct object *o; unsigned char sha1_buf[20]; @@ -619,7 +619,7 @@ static void receive_needs(void) } } if (debug_fd) - write_in_full(debug_fd, "#E\n", 3); + write_str_in_full(debug_fd, "#E\n"); if (!use_sideband && daemon_mode) no_progress = 1; -- cgit v1.2.3 From fe0a3cb23c7930be419937825591388465ceb47f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 14 Oct 2009 11:51:03 -0700 Subject: info/grafts: allow trailing whitespaces at the end of line When creating an info/grafts under windows, one typically gets a CRLF file. There is no good reason to forbid trailing CR at the end of the line (for that matter, any trailing whitespaces); the code allowed only LF simply because that was good enough for the platforms with LF line endings. Signed-off-by: Junio C Hamano --- commit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index aa3b35b6a8..eee5ab803b 100644 --- a/commit.c +++ b/commit.c @@ -136,8 +136,8 @@ struct commit_graft *read_graft_line(char *buf, int len) int i; struct commit_graft *graft = NULL; - if (buf[len-1] == '\n') - buf[--len] = 0; + while (len && isspace(buf[len-1])) + buf[--len] = '\0'; if (buf[0] == '#' || buf[0] == '\0') return NULL; if ((len + 1) % 41) { -- cgit v1.2.3 From a97a74686d70a318cd802003498054cc1e8b0ae2 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Fri, 9 Oct 2009 12:21:57 +0200 Subject: Introduce commit notes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit notes are blobs which are shown together with the commit message. These blobs are taken from the notes ref, which you can configure by the config variable core.notesRef, which in turn can be overridden by the environment variable GIT_NOTES_REF. The notes ref is a branch which contains "files" whose names are the names of the corresponding commits (i.e. the SHA-1). The rationale for putting this information into a ref is this: we want to be able to fetch and possibly union-merge the notes, maybe even look at the date when a note was introduced, and we want to store them efficiently together with the other objects. This patch has been improved by the following contributions: - Thomas Rast: fix core.notesRef documentation - Tor Arne Vestbø: fix printing of multi-line notes - Alex Riesen: Using char array instead of char pointer costs less BSS - Johan Herland: Plug leak when msg is good, but msglen or type causes return Signed-off-by: Johannes Schindelin Signed-off-by: Thomas Rast Signed-off-by: Tor Arne Vestbø Signed-off-by: Johan Herland Signed-off-by: Junio C Hamano get_commit_notes(): Plug memory leak when 'if' triggers, but not because of read_sha1_file() failure --- Documentation/config.txt | 13 +++++++++ Makefile | 2 ++ cache.h | 4 +++ commit.c | 1 + config.c | 5 ++++ environment.c | 1 + notes.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++ notes.h | 7 +++++ pretty.c | 5 ++++ 9 files changed, 108 insertions(+) create mode 100644 notes.c create mode 100644 notes.h (limited to 'commit.c') diff --git a/Documentation/config.txt b/Documentation/config.txt index cd1781498e..57d64e4d99 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -454,6 +454,19 @@ On some file system/operating system combinations, this is unreliable. Set this config setting to 'rename' there; However, This will remove the check that makes sure that existing object files will not get overwritten. +core.notesRef:: + When showing commit messages, also show notes which are stored in + the given ref. This ref is expected to contain files named + after the full SHA-1 of the commit they annotate. ++ +If such a file exists in the given ref, the referenced blob is read, and +appended to the commit message, separated by a "Notes:" line. If the +given ref itself does not exist, it is not an error, but means that no +notes should be printed. ++ +This setting defaults to "refs/notes/commits", and can be overridden by +the `GIT_NOTES_REF` environment variable. + add.ignore-errors:: Tells 'git-add' to continue adding files when some files cannot be added due to indexing errors. Equivalent to the '--ignore-errors' diff --git a/Makefile b/Makefile index fea237bc80..9a6a729868 100644 --- a/Makefile +++ b/Makefile @@ -432,6 +432,7 @@ LIB_H += ll-merge.h LIB_H += log-tree.h LIB_H += mailmap.h LIB_H += merge-recursive.h +LIB_H += notes.h LIB_H += object.h LIB_H += pack.h LIB_H += pack-refs.h @@ -516,6 +517,7 @@ LIB_OBJS += match-trees.o LIB_OBJS += merge-file.o LIB_OBJS += merge-recursive.o LIB_OBJS += name-hash.o +LIB_OBJS += notes.o LIB_OBJS += object.o LIB_OBJS += pack-check.o LIB_OBJS += pack-refs.o diff --git a/cache.h b/cache.h index a5eeead1e2..4f0ddeca11 100644 --- a/cache.h +++ b/cache.h @@ -372,6 +372,8 @@ static inline enum object_type object_type(unsigned int mode) #define GITATTRIBUTES_FILE ".gitattributes" #define INFOATTRIBUTES_FILE "info/attributes" #define ATTRIBUTE_MACRO_PREFIX "[attr]" +#define GIT_NOTES_REF_ENVIRONMENT "GIT_NOTES_REF" +#define GIT_NOTES_DEFAULT_REF "refs/notes/commits" extern int is_bare_repository_cfg; extern int is_bare_repository(void); @@ -567,6 +569,8 @@ enum object_creation_mode { extern enum object_creation_mode object_creation_mode; +extern char *notes_ref_name; + extern int grafts_replace_parents; #define GIT_REPO_VERSION 0 diff --git a/commit.c b/commit.c index fedbd5e526..5ade8edf81 100644 --- a/commit.c +++ b/commit.c @@ -5,6 +5,7 @@ #include "utf8.h" #include "diff.h" #include "revision.h" +#include "notes.h" int save_commit_buffer = 1; diff --git a/config.c b/config.c index c644061136..51f22088e7 100644 --- a/config.c +++ b/config.c @@ -467,6 +467,11 @@ static int git_default_core_config(const char *var, const char *value) return 0; } + if (!strcmp(var, "core.notesref")) { + notes_ref_name = xstrdup(value); + return 0; + } + if (!strcmp(var, "core.pager")) return git_config_string(&pager_program, var, value); diff --git a/environment.c b/environment.c index 5de6837840..571ab56b7e 100644 --- a/environment.c +++ b/environment.c @@ -49,6 +49,7 @@ enum push_default_type push_default = PUSH_DEFAULT_MATCHING; #define OBJECT_CREATION_MODE OBJECT_CREATION_USES_HARDLINKS #endif enum object_creation_mode object_creation_mode = OBJECT_CREATION_MODE; +char *notes_ref_name; int grafts_replace_parents = 1; /* Parallel index stat data preload? */ diff --git a/notes.c b/notes.c new file mode 100644 index 0000000000..66379ffd22 --- /dev/null +++ b/notes.c @@ -0,0 +1,70 @@ +#include "cache.h" +#include "commit.h" +#include "notes.h" +#include "refs.h" +#include "utf8.h" +#include "strbuf.h" + +static int initialized; + +void get_commit_notes(const struct commit *commit, struct strbuf *sb, + const char *output_encoding) +{ + static const char utf8[] = "utf-8"; + struct strbuf name = STRBUF_INIT; + unsigned char sha1[20]; + char *msg, *msg_p; + unsigned long linelen, msglen; + enum object_type type; + + if (!initialized) { + const char *env = getenv(GIT_NOTES_REF_ENVIRONMENT); + if (env) + notes_ref_name = getenv(GIT_NOTES_REF_ENVIRONMENT); + else if (!notes_ref_name) + notes_ref_name = GIT_NOTES_DEFAULT_REF; + if (notes_ref_name && read_ref(notes_ref_name, sha1)) + notes_ref_name = NULL; + initialized = 1; + } + + if (!notes_ref_name) + return; + + strbuf_addf(&name, "%s:%s", notes_ref_name, + sha1_to_hex(commit->object.sha1)); + if (get_sha1(name.buf, sha1)) + return; + + if (!(msg = read_sha1_file(sha1, &type, &msglen)) || !msglen || + type != OBJ_BLOB) { + free(msg); + return; + } + + if (output_encoding && *output_encoding && + strcmp(utf8, output_encoding)) { + char *reencoded = reencode_string(msg, output_encoding, utf8); + if (reencoded) { + free(msg); + msg = reencoded; + msglen = strlen(msg); + } + } + + /* we will end the annotation by a newline anyway */ + if (msglen && msg[msglen - 1] == '\n') + msglen--; + + strbuf_addstr(sb, "\nNotes:\n"); + + for (msg_p = msg; msg_p < msg + msglen; msg_p += linelen + 1) { + linelen = strchrnul(msg_p, '\n') - msg_p; + + strbuf_addstr(sb, " "); + strbuf_add(sb, msg_p, linelen); + strbuf_addch(sb, '\n'); + } + + free(msg); +} diff --git a/notes.h b/notes.h new file mode 100644 index 0000000000..79d21b65f5 --- /dev/null +++ b/notes.h @@ -0,0 +1,7 @@ +#ifndef NOTES_H +#define NOTES_H + +void get_commit_notes(const struct commit *commit, struct strbuf *sb, + const char *output_encoding); + +#endif diff --git a/pretty.c b/pretty.c index f5983f8baa..e25db81eaa 100644 --- a/pretty.c +++ b/pretty.c @@ -6,6 +6,7 @@ #include "string-list.h" #include "mailmap.h" #include "log-tree.h" +#include "notes.h" #include "color.h" static char *user_format; @@ -975,5 +976,9 @@ void pretty_print_commit(enum cmit_fmt fmt, const struct commit *commit, */ if (fmt == CMIT_FMT_EMAIL && sb->len <= beginning_of_body) strbuf_addch(sb, '\n'); + + if (fmt != CMIT_FMT_ONELINE) + get_commit_notes(commit, sb, encoding); + free(reencoded); } -- cgit v1.2.3 From edace6f02eeae6f4a06ed1e4f6308703523d8535 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Fri, 30 Oct 2009 17:47:23 -0700 Subject: fetch-pack: Use a strbuf to compose the want list This change is being offered as a refactoring to make later commits in the smart HTTP series easier. By changing the enabled capabilities to be formatted in a strbuf it is easier to add a new capability to the set of supported capabilities. By formatting the want portion of the request into a strbuf and writing it as a whole block we can later decide to hold onto the req_buf (instead of releasing it) to recycle in stateless communications. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- builtin-fetch-pack.c | 52 ++++++++++++++++++++++++++++++++++------------------ commit.c | 10 ++++------ commit.h | 2 +- 3 files changed, 39 insertions(+), 25 deletions(-) (limited to 'commit.c') diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 629735f547..783c2b0834 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -165,6 +165,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, const unsigned char *sha1; unsigned in_vain = 0; int got_continue = 0; + struct strbuf req_buf = STRBUF_INIT; if (marked) for_each_ref(clear_marks, NULL); @@ -175,6 +176,7 @@ static int find_common(int fd[2], unsigned char *result_sha1, fetching = 0; for ( ; refs ; refs = refs->next) { unsigned char *remote = refs->old_sha1; + const char *remote_hex; struct object *o; /* @@ -192,27 +194,36 @@ static int find_common(int fd[2], unsigned char *result_sha1, continue; } - if (!fetching) - packet_write(fd[1], "want %s%s%s%s%s%s%s%s\n", - sha1_to_hex(remote), - (multi_ack ? " multi_ack" : ""), - (use_sideband == 2 ? " side-band-64k" : ""), - (use_sideband == 1 ? " side-band" : ""), - (args.use_thin_pack ? " thin-pack" : ""), - (args.no_progress ? " no-progress" : ""), - (args.include_tag ? " include-tag" : ""), - (prefer_ofs_delta ? " ofs-delta" : "")); - else - packet_write(fd[1], "want %s\n", sha1_to_hex(remote)); + remote_hex = sha1_to_hex(remote); + if (!fetching) { + struct strbuf c = STRBUF_INIT; + if (multi_ack) strbuf_addstr(&c, " multi_ack"); + if (use_sideband == 2) strbuf_addstr(&c, " side-band-64k"); + if (use_sideband == 1) strbuf_addstr(&c, " side-band"); + if (args.use_thin_pack) strbuf_addstr(&c, " thin-pack"); + if (args.no_progress) strbuf_addstr(&c, " no-progress"); + if (args.include_tag) strbuf_addstr(&c, " include-tag"); + if (prefer_ofs_delta) strbuf_addstr(&c, " ofs-delta"); + packet_buf_write(&req_buf, "want %s%s\n", remote_hex, c.buf); + strbuf_release(&c); + } else + packet_buf_write(&req_buf, "want %s\n", remote_hex); fetching++; } + + if (!fetching) { + strbuf_release(&req_buf); + packet_flush(fd[1]); + return 1; + } + if (is_repository_shallow()) - write_shallow_commits(fd[1], 1); + write_shallow_commits(&req_buf, 1); if (args.depth > 0) - packet_write(fd[1], "deepen %d", args.depth); - packet_flush(fd[1]); - if (!fetching) - return 1; + packet_buf_write(&req_buf, "deepen %d", args.depth); + packet_buf_flush(&req_buf); + + safe_write(fd[1], req_buf.buf, req_buf.len); if (args.depth > 0) { char line[1024]; @@ -296,6 +307,8 @@ done: multi_ack = 0; flushes++; } + strbuf_release(&req_buf); + while (flushes || multi_ack) { int ack = get_ack(fd[0], result_sha1); if (ack) { @@ -809,6 +822,7 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, if (args.depth > 0) { struct cache_time mtime; + struct strbuf sb = STRBUF_INIT; char *shallow = git_path("shallow"); int fd; @@ -826,12 +840,14 @@ struct ref *fetch_pack(struct fetch_pack_args *my_args, fd = hold_lock_file_for_update(&lock, shallow, LOCK_DIE_ON_ERROR); - if (!write_shallow_commits(fd, 0)) { + if (!write_shallow_commits(&sb, 0) + || write_in_full(fd, sb.buf, sb.len) != sb.len) { unlink_or_warn(shallow); rollback_lock_file(&lock); } else { commit_lock_file(&lock); } + strbuf_release(&sb); } reprepare_packed_git(); diff --git a/commit.c b/commit.c index fedbd5e526..471efb0566 100644 --- a/commit.c +++ b/commit.c @@ -199,7 +199,7 @@ struct commit_graft *lookup_commit_graft(const unsigned char *sha1) return commit_graft[pos]; } -int write_shallow_commits(int fd, int use_pack_protocol) +int write_shallow_commits(struct strbuf *out, int use_pack_protocol) { int i, count = 0; for (i = 0; i < commit_graft_nr; i++) @@ -208,12 +208,10 @@ int write_shallow_commits(int fd, int use_pack_protocol) sha1_to_hex(commit_graft[i]->sha1); count++; if (use_pack_protocol) - packet_write(fd, "shallow %s", hex); + packet_buf_write(out, "shallow %s", hex); else { - if (write_in_full(fd, hex, 40) != 40) - break; - if (write_str_in_full(fd, "\n") != 1) - break; + strbuf_addstr(out, hex); + strbuf_addch(out, '\n'); } } return count; diff --git a/commit.h b/commit.h index f4fc5c5589..817c75c02f 100644 --- a/commit.h +++ b/commit.h @@ -131,7 +131,7 @@ extern struct commit_list *get_octopus_merge_bases(struct commit_list *in); extern int register_shallow(const unsigned char *sha1); extern int unregister_shallow(const unsigned char *sha1); -extern int write_shallow_commits(int fd, int use_pack_protocol); +extern int write_shallow_commits(struct strbuf *out, int use_pack_protocol); extern int is_repository_shallow(void); extern struct commit_list *get_shallow_commits(struct object_array *heads, int depth, int shallow_flag, int not_shallow_flag); -- cgit v1.2.3 From 65d41d48a4e4e795d64dd7842a44d693b741bf31 Mon Sep 17 00:00:00 2001 From: Jeff King Date: Fri, 29 Jan 2010 05:28:44 -0500 Subject: fix memcpy of overlapping area Caught by valgrind in t5500, but it is pretty obvious from reading the code that this is shifting elements of an array to the left, which needs memmove. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- commit.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'commit.c') diff --git a/commit.c b/commit.c index 6393e1b362..a51d2cd1be 100644 --- a/commit.c +++ b/commit.c @@ -225,7 +225,7 @@ int unregister_shallow(const unsigned char *sha1) if (pos < 0) return -1; if (pos + 1 < commit_graft_nr) - memcpy(commit_graft + pos, commit_graft + pos + 1, + memmove(commit_graft + pos, commit_graft + pos + 1, sizeof(struct commit_graft *) * (commit_graft_nr - pos - 1)); commit_graft_nr--; -- cgit v1.2.3