From 0aee3d6d4e2ba3278ad0f789fc7c0a9742fc5a07 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 5 Mar 2006 12:25:43 +0000 Subject: [PATCH 01/15] gitignore: Ignore some more boring things. Signed-off-by: Mark Wooding Signed-off-by: Junio C Hamano --- .gitignore | 1 + t/.gitignore | 1 + 2 files changed, 2 insertions(+) create mode 100644 t/.gitignore diff --git a/.gitignore b/.gitignore index 5be239a4aa..abbc509e13 100644 --- a/.gitignore +++ b/.gitignore @@ -130,3 +130,4 @@ libgit.a *.o *.py[co] config.mak +git-blame diff --git a/t/.gitignore b/t/.gitignore new file mode 100644 index 0000000000..fad67c097b --- /dev/null +++ b/t/.gitignore @@ -0,0 +1 @@ +trash From 8911db70f8b84b2e96b328eeca9e5d7701c22479 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Sun, 5 Mar 2006 16:14:31 +0000 Subject: [PATCH 02/15] contrib/emacs/Makefile: Provide tool for byte-compiling files. Signed-off-by: Mark Wooding Signed-off-by: Junio C Hamano --- contrib/emacs/.gitignore | 1 + contrib/emacs/Makefile | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 contrib/emacs/.gitignore create mode 100644 contrib/emacs/Makefile diff --git a/contrib/emacs/.gitignore b/contrib/emacs/.gitignore new file mode 100644 index 0000000000..c531d9867f --- /dev/null +++ b/contrib/emacs/.gitignore @@ -0,0 +1 @@ +*.elc diff --git a/contrib/emacs/Makefile b/contrib/emacs/Makefile new file mode 100644 index 0000000000..d3619db510 --- /dev/null +++ b/contrib/emacs/Makefile @@ -0,0 +1,20 @@ +## Build and install stuff + +EMACS = emacs + +ELC = git.elc vc-git.elc +INSTALL = install +INSTALL_ELC = $(INSTALL) -m 644 +prefix = $(HOME) +emacsdir = $(prefix)/share/emacs/site-lisp + +all: $(ELC) + +install: all + $(INSTALL) -d $(emacsdir) + $(INSTALL_ELC) $(ELC) $(emacsdir) + +%.elc: %.el + $(EMACS) --batch --eval '(byte-compile-file "$<")' + +clean:; rm -f $(ELC) From 872d001f7f576b2d32f6278dc265d6449787b714 Mon Sep 17 00:00:00 2001 From: Jeff Muizelaar Date: Sun, 5 Mar 2006 16:18:19 -0500 Subject: [PATCH 03/15] documentation: add 'see also' sections to git-rm and git-add Pair up git-add and git-rm by adding a 'see also' section that references the opposite command to each of their documentation files. Signed-off-by: Junio C Hamano --- Documentation/git-add.txt | 3 +++ Documentation/git-rm.txt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/Documentation/git-add.txt b/Documentation/git-add.txt index 7e293834d1..5b7c354554 100644 --- a/Documentation/git-add.txt +++ b/Documentation/git-add.txt @@ -65,6 +65,9 @@ git-add git-*.sh:: (i.e. you are listing the files explicitly), it does not add `subdir/git-foo.sh` to the index. +See Also +-------- +gitlink:git-rm[1] Author ------ diff --git a/Documentation/git-rm.txt b/Documentation/git-rm.txt index 401bfb2d9c..d8a5afae03 100644 --- a/Documentation/git-rm.txt +++ b/Documentation/git-rm.txt @@ -74,6 +74,9 @@ git-rm -f git-*.sh:: shell expand the asterisk (i.e. you are listing the files explicitly), it does not remove `subdir/git-foo.sh`. +See Also +-------- +gitlink:git-add[1] Author ------ From ea5ed3abce724725360be88663cec1add7547d46 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 5 Mar 2006 09:53:52 -0800 Subject: [PATCH 04/15] get_revision(): do not dig deeper when we know we are at the end. This resurrects the special casing for "rev-list -n 1" which avoided reading parents unnecessarily. Signed-off-by: Junio C Hamano --- revision.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/revision.c b/revision.c index a3df810076..2a33637f62 100644 --- a/revision.c +++ b/revision.c @@ -684,13 +684,11 @@ static void rewrite_parents(struct commit *commit) struct commit *get_revision(struct rev_info *revs) { struct commit_list *list = revs->commits; - struct commit *commit; if (!list) return NULL; /* Check the max_count ... */ - commit = list->item; switch (revs->max_count) { case -1: break; @@ -701,22 +699,28 @@ struct commit *get_revision(struct rev_info *revs) } do { - commit = pop_most_recent_commit(&revs->commits, SEEN); + struct commit *commit = revs->commits->item; + if (commit->object.flags & (UNINTERESTING|SHOWN)) - continue; + goto next; if (revs->min_age != -1 && (commit->date > revs->min_age)) - continue; + goto next; if (revs->max_age != -1 && (commit->date < revs->max_age)) return NULL; if (revs->no_merges && commit->parents && commit->parents->next) - continue; + goto next; if (revs->paths && revs->dense) { if (!(commit->object.flags & TREECHANGE)) - continue; + goto next; rewrite_parents(commit); } + /* More to go? */ + if (revs->max_count) + pop_most_recent_commit(&revs->commits, SEEN); commit->object.flags |= SHOWN; return commit; +next: + pop_most_recent_commit(&revs->commits, SEEN); } while (revs->commits); return NULL; } From ea4c7f9bf69e781dd0cd88d2bccb2bf5cc15c9a7 Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Sun, 5 Mar 2006 12:03:51 +0100 Subject: [PATCH 05/15] git-blame: Make the output human readable The default output mode is slightly different from git-annotate's. However, git-annotate's output mode can be obtained by using the '-c' flag. Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- Makefile | 4 ++ blame.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 148 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index b6d8804d4b..eb1887d771 100644 --- a/Makefile +++ b/Makefile @@ -534,6 +534,10 @@ git-rev-list$X: rev-list.o $(LIB_FILE) $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(OPENSSL_LIBSSL) +git-blame$X: blame.o $(LIB_FILE) + $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ + $(LIBS) -lm + init-db.o: init-db.c $(CC) -c $(ALL_CFLAGS) \ -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c diff --git a/blame.c b/blame.c index 562940eced..168b1f5fe5 100644 --- a/blame.c +++ b/blame.c @@ -5,6 +5,7 @@ #include #include #include +#include #include "cache.h" #include "refs.h" @@ -17,8 +18,15 @@ #define DEBUG 0 -struct commit **blame_lines; -int num_blame_lines; +static const char blame_usage[] = "[-c] [-l] [--] file [commit]\n" + " -c, --compability Use the same output mode as git-annotate (Default: off)\n" + " -l, --long Show long commit SHA1 (Default: off)\n" + " -h, --help This message"; + +static struct commit **blame_lines; +static int num_blame_lines; +static char* blame_contents; +static int blame_len; struct util_info { int *line_map; @@ -390,9 +398,8 @@ static void init_first_commit(struct commit* commit, const char* filename) alloc_line_map(commit); util = commit->object.util; - num_blame_lines = util->num_lines; - for (i = 0; i < num_blame_lines; i++) + for (i = 0; i < util->num_lines; i++) util->line_map[i] = i; } @@ -414,6 +421,9 @@ static void process_commits(struct rev_info *rev, const char *path, util = commit->object.util; num_blame_lines = util->num_lines; blame_lines = xmalloc(sizeof(struct commit *) * num_blame_lines); + blame_contents = util->buf; + blame_len = util->size; + for (i = 0; i < num_blame_lines; i++) blame_lines[i] = NULL; @@ -501,32 +511,128 @@ static void process_commits(struct rev_info *rev, const char *path, } while ((commit = get_revision(rev)) != NULL); } +struct commit_info +{ + char* author; + char* author_mail; + unsigned long author_time; + char* author_tz; +}; + +static void get_commit_info(struct commit* commit, struct commit_info* ret) +{ + int len; + char* tmp; + static char author_buf[1024]; + + tmp = strstr(commit->buffer, "\nauthor ") + 8; + len = index(tmp, '\n') - tmp; + ret->author = author_buf; + memcpy(ret->author, tmp, len); + + tmp = ret->author; + tmp += len; + *tmp = 0; + while(*tmp != ' ') + tmp--; + ret->author_tz = tmp+1; + + *tmp = 0; + while(*tmp != ' ') + tmp--; + ret->author_time = strtoul(tmp, NULL, 10); + + *tmp = 0; + while(*tmp != ' ') + tmp--; + ret->author_mail = tmp + 1; + + *tmp = 0; +} + +char* format_time(unsigned long time, const char* tz) +{ + static char time_buf[128]; + time_t t = time; + + strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", gmtime(&t)); + strcat(time_buf, tz); + return time_buf; +} + int main(int argc, const char **argv) { int i; struct commit *initial = NULL; unsigned char sha1[20]; - const char* filename; + + const char *filename = NULL, *commit = NULL; + char filename_buf[256]; + int sha1_len = 8; + int compability = 0; + int options = 1; + int num_args; const char* args[10]; struct rev_info rev; - setup_git_directory(); + struct commit_info ci; + const char *buf; + int max_digits; - if (argc != 3) - die("Usage: blame commit-ish file"); + const char* prefix = setup_git_directory(); + for(i = 1; i < argc; i++) { + if(options) { + if(!strcmp(argv[i], "-h") || + !strcmp(argv[i], "--help")) + usage(blame_usage); + else if(!strcmp(argv[i], "-l") || + !strcmp(argv[i], "--long")) { + sha1_len = 20; + continue; + } else if(!strcmp(argv[i], "-c") || + !strcmp(argv[i], "--compability")) { + compability = 1; + continue; + } else if(!strcmp(argv[i], "--")) { + options = 0; + continue; + } else if(argv[i][0] == '-') + usage(blame_usage); + else + options = 0; + } - filename = argv[2]; + if(!options) { + if(!filename) + filename = argv[i]; + else if(!commit) + commit = argv[i]; + else + usage(blame_usage); + } + } + + if(!filename) + usage(blame_usage); + if(!commit) + commit = "HEAD"; + + if(prefix) + sprintf(filename_buf, "%s%s", prefix, filename); + else + strcpy(filename_buf, filename); + filename = filename_buf; { - struct commit* commit; - if (get_sha1(argv[1], sha1)) - die("get_sha1 failed"); - commit = lookup_commit_reference(sha1); + struct commit* c; + if (get_sha1(commit, sha1)) + die("get_sha1 failed, commit '%s' not found", commit); + c = lookup_commit_reference(sha1); - if (fill_util_info(commit, filename)) { - printf("%s not found in %s\n", filename, argv[1]); + if (fill_util_info(c, filename)) { + printf("%s not found in %s\n", filename, commit); return 1; } } @@ -535,7 +641,7 @@ int main(int argc, const char **argv) args[num_args++] = NULL; args[num_args++] = "--topo-order"; args[num_args++] = "--remove-empty"; - args[num_args++] = argv[1]; + args[num_args++] = commit; args[num_args++] = "--"; args[num_args++] = filename; args[num_args] = NULL; @@ -544,13 +650,33 @@ int main(int argc, const char **argv) prepare_revision_walk(&rev); process_commits(&rev, filename, &initial); + buf = blame_contents; + max_digits = 1 + log(num_blame_lines+1)/log(10); for (i = 0; i < num_blame_lines; i++) { struct commit *c = blame_lines[i]; if (!c) c = initial; - printf("%d %.8s\n", i, sha1_to_hex(c->object.sha1)); -// printf("%d %s\n", i, find_unique_abbrev(blame_lines[i]->object.sha1, 6)); + get_commit_info(c, &ci); + fwrite(sha1_to_hex(c->object.sha1), sha1_len, 1, stdout); + if(compability) + printf("\t(%10s\t%10s\t%d)", ci.author, + format_time(ci.author_time, ci.author_tz), i+1); + else + printf(" (%-15.15s %10s %*d) ", ci.author, + format_time(ci.author_time, ci.author_tz), + max_digits, i+1); + + if(i == num_blame_lines - 1) { + fwrite(buf, blame_len - (buf - blame_contents), + 1, stdout); + if(blame_contents[blame_len-1] != '\n') + putc('\n', stdout); + } else { + char* next_buf = index(buf, '\n') + 1; + fwrite(buf, next_buf - buf, 1, stdout); + buf = next_buf; + } } if (DEBUG) { From a0fb95e3199810268cfe88c7c4ff0d9958e07062 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 5 Mar 2006 14:46:36 -0800 Subject: [PATCH 06/15] blame: avoid -lm by not using log(). ... as suggested on the list. Signed-off-by: Junio C Hamano --- Makefile | 4 ---- blame.c | 6 ++++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index eb1887d771..b6d8804d4b 100644 --- a/Makefile +++ b/Makefile @@ -534,10 +534,6 @@ git-rev-list$X: rev-list.o $(LIB_FILE) $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ $(LIBS) $(OPENSSL_LIBSSL) -git-blame$X: blame.o $(LIB_FILE) - $(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) \ - $(LIBS) -lm - init-db.o: init-db.c $(CC) -c $(ALL_CFLAGS) \ -DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"' $*.c diff --git a/blame.c b/blame.c index 168b1f5fe5..b551dd5aa3 100644 --- a/blame.c +++ b/blame.c @@ -589,7 +589,7 @@ int main(int argc, const char **argv) usage(blame_usage); else if(!strcmp(argv[i], "-l") || !strcmp(argv[i], "--long")) { - sha1_len = 20; + sha1_len = 40; continue; } else if(!strcmp(argv[i], "-c") || !strcmp(argv[i], "--compability")) { @@ -651,7 +651,9 @@ int main(int argc, const char **argv) process_commits(&rev, filename, &initial); buf = blame_contents; - max_digits = 1 + log(num_blame_lines+1)/log(10); + for (max_digits = 1, i = 10; i <= num_blame_lines + 1; max_digits++) + i *= 10; + for (i = 0; i < num_blame_lines; i++) { struct commit *c = blame_lines[i]; if (!c) From cfea8e077b9a8956080688ab40e9efd812c2a0c5 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 5 Mar 2006 14:48:01 -0800 Subject: [PATCH 07/15] blame and annotate: show localtime with timezone. Earlier they showed gmtime and timezone, which was inconsistent with the way our commits and tags are pretty-printed. Signed-off-by: Junio C Hamano --- blame.c | 15 ++++++++++++--- git-annotate.perl | 8 +++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/blame.c b/blame.c index b551dd5aa3..ffc1f52add 100644 --- a/blame.c +++ b/blame.c @@ -550,13 +550,22 @@ static void get_commit_info(struct commit* commit, struct commit_info* ret) *tmp = 0; } -char* format_time(unsigned long time, const char* tz) +static const char* format_time(unsigned long time, const char* tz_str) { static char time_buf[128]; time_t t = time; + int minutes, tz; + struct tm *tm; - strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", gmtime(&t)); - strcat(time_buf, tz); + tz = atoi(tz_str); + minutes = tz < 0 ? -tz : tz; + minutes = (minutes / 100)*60 + (minutes % 100); + minutes = tz < 0 ? -minutes : minutes; + t = time + minutes * 60; + tm = gmtime(&t); + + strftime(time_buf, sizeof(time_buf), "%Y-%m-%d %H:%M:%S ", tm); + strcat(time_buf, tz_str); return time_buf; } diff --git a/git-annotate.perl b/git-annotate.perl index d93ee19c7e..b113def97b 100755 --- a/git-annotate.perl +++ b/git-annotate.perl @@ -418,7 +418,13 @@ sub format_date { return $_[0]; } my ($timestamp, $timezone) = split(' ', $_[0]); - return strftime("%Y-%m-%d %H:%M:%S " . $timezone, gmtime($timestamp)); + my $minutes = abs($timezone); + $minutes = int($minutes / 100) * 60 + ($minutes % 100); + if ($timezone < 0) { + $minutes = -$minutes; + } + my $t = $timestamp + $minutes * 60; + return strftime("%Y-%m-%d %H:%M:%S " . $timezone, gmtime($t)); } # Copied from git-send-email.perl - We need a Git.pm module.. From 8752d11d60e8f48b6e242e7f504c8e8fd7eabb92 Mon Sep 17 00:00:00 2001 From: Fredrik Kuivinen Date: Sun, 5 Mar 2006 12:13:34 +0100 Subject: [PATCH 08/15] git-blame: Use the same tests for git-blame as for git-annotate Signed-off-by: Fredrik Kuivinen Signed-off-by: Junio C Hamano --- t/annotate-tests.sh | 86 +++++++++++++++++++++++++++++++++++++++++++++ t/t8001-annotate.sh | 85 ++------------------------------------------ t/t8002-blame.sh | 9 +++++ 3 files changed, 97 insertions(+), 83 deletions(-) create mode 100644 t/annotate-tests.sh create mode 100755 t/t8002-blame.sh diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh new file mode 100644 index 0000000000..54a4dfb9f4 --- /dev/null +++ b/t/annotate-tests.sh @@ -0,0 +1,86 @@ +# This file isn't used as a test script directly, instead it is +# sourced from t8001-annotate.sh and t8001-blame.sh. + +test_expect_success \ + 'prepare reference tree' \ + 'echo "1A quick brown fox jumps over the" >file && + echo "lazy dog" >>file && + git add file + GIT_AUTHOR_NAME="A" git commit -a -m "Initial."' + +test_expect_success \ + 'check all lines blamed on A' \ + '[ $(git annotate file | awk "{print \$3}" | grep -c "A") == 2 ]' + +test_expect_success \ + 'Setup new lines blamed on B' \ + 'echo "2A quick brown fox jumps over the" >>file && + echo "lazy dog" >> file && + GIT_AUTHOR_NAME="B" git commit -a -m "Second."' + +test_expect_success \ + 'Two lines blamed on A' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "A") == 2 ]' + +test_expect_success \ + 'Two lines blamed on B' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "B") == 2 ]' + +test_expect_success \ + 'merge-setup part 1' \ + 'git checkout -b branch1 master && + echo "3A slow green fox jumps into the" >> file && + echo "well." >> file && + GIT_AUTHOR_NAME="B1" git commit -a -m "Branch1-1"' + +test_expect_success \ + 'Two lines blamed on A' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^A$") == 2 ]' + +test_expect_success \ + 'Two lines blamed on B' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^B$") == 2 ]' + +test_expect_success \ + 'Two lines blamed on B1' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^B1$") == 2 ]' + +test_expect_success \ + 'merge-setup part 2' \ + 'git checkout -b branch2 master && + sed -e "s/2A quick brown/4A quick brown lazy dog/" < file > file.new && + mv file.new file && + GIT_AUTHOR_NAME="B2" git commit -a -m "Branch2-1"' + +test_expect_success \ + 'Two lines blamed on A' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^A$") == 2 ]' + +test_expect_success \ + 'One line blamed on B' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^B$") == 1 ]' + +test_expect_success \ + 'One line blamed on B2' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^B2$") == 1 ]' + + +test_expect_success \ + 'merge-setup part 3' \ + 'git pull . branch1' + +test_expect_success \ + 'Two lines blamed on A' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^A$") == 2 ]' + +test_expect_success \ + 'One line blamed on B' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^B$") == 1 ]' + +test_expect_success \ + 'Two lines blamed on B1' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^B1$") == 2 ]' + +test_expect_success \ + 'One line blamed on B2' \ + '[ $($PROG file | awk "{print \$3}" | grep -c "^B2$") == 1 ]' diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh index 172908a5b0..9e5a04b0f9 100755 --- a/t/t8001-annotate.sh +++ b/t/t8001-annotate.sh @@ -3,88 +3,7 @@ test_description='git-annotate' . ./test-lib.sh -test_expect_success \ - 'prepare reference tree' \ - 'echo "1A quick brown fox jumps over the" >file && - echo "lazy dog" >>file && - git add file - GIT_AUTHOR_NAME="A" git commit -a -m "Initial."' - -test_expect_success \ - 'check all lines blamed on A' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "A") == 2 ]' - -test_expect_success \ - 'Setup new lines blamed on B' \ - 'echo "2A quick brown fox jumps over the" >>file && - echo "lazy dog" >> file && - GIT_AUTHOR_NAME="B" git commit -a -m "Second."' - -test_expect_success \ - 'Two lines blamed on A' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "A") == 2 ]' - -test_expect_success \ - 'Two lines blamed on B' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "B") == 2 ]' - -test_expect_success \ - 'merge-setup part 1' \ - 'git checkout -b branch1 master && - echo "3A slow green fox jumps into the" >> file && - echo "well." >> file && - GIT_AUTHOR_NAME="B1" git commit -a -m "Branch1-1"' - -test_expect_success \ - 'Two lines blamed on A' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^A$") == 2 ]' - -test_expect_success \ - 'Two lines blamed on B' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^B$") == 2 ]' - -test_expect_success \ - 'Two lines blamed on B1' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^B1$") == 2 ]' - -test_expect_success \ - 'merge-setup part 2' \ - 'git checkout -b branch2 master && - sed -e "s/2A quick brown/4A quick brown lazy dog/" < file > file.new && - mv file.new file && - GIT_AUTHOR_NAME="B2" git commit -a -m "Branch2-1"' - -test_expect_success \ - 'Two lines blamed on A' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^A$") == 2 ]' - -test_expect_success \ - 'One line blamed on B' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^B$") == 1 ]' - -test_expect_success \ - 'One line blamed on B2' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^B2$") == 1 ]' - - -test_expect_success \ - 'merge-setup part 3' \ - 'git pull . branch1' - -test_expect_success \ - 'Two lines blamed on A' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^A$") == 2 ]' - -test_expect_success \ - 'One line blamed on B' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^B$") == 1 ]' - -test_expect_success \ - 'Two lines blamed on B1' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^B1$") == 2 ]' - -test_expect_success \ - 'One line blamed on B2' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "^B2$") == 1 ]' +PROG='git annotate' +source ../annotate-tests.sh test_done diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh new file mode 100755 index 0000000000..1036c54d30 --- /dev/null +++ b/t/t8002-blame.sh @@ -0,0 +1,9 @@ +#!/bin/sh + +test_description='git-blame' +. ./test-lib.sh + +PROG='git blame -c' +source ../annotate-tests.sh + +test_done From 604c86d15bb319a1e93ba218fca48ce1c500ae52 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 5 Mar 2006 14:43:56 -0800 Subject: [PATCH 09/15] blame: avoid "diff -u0". As Linus suggests, use "diff -u -U 0" instead. Signed-off-by: Junio C Hamano --- blame.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/blame.c b/blame.c index ffc1f52add..fca22f9000 100644 --- a/blame.c +++ b/blame.c @@ -92,7 +92,7 @@ static struct patch *get_patch(struct commit *commit, struct commit *other) die("write failed: %s", strerror(errno)); close(fd); - sprintf(diff_cmd, "diff -u0 %s %s", tmp_path1, tmp_path2); + sprintf(diff_cmd, "diff -u -U 0 %s %s", tmp_path1, tmp_path2); fin = popen(diff_cmd, "r"); if (!fin) die("popen failed: %s", strerror(errno)); From bd494fc76be09ab61f8285f1299e2474b0554a81 Mon Sep 17 00:00:00 2001 From: "Dmitry V. Levin" Date: Mon, 6 Mar 2006 03:00:48 +0300 Subject: [PATCH 10/15] git/Documentation: fix SYNOPSIS style bugs This trivial patch fixes SYNOPSIS style bugs. Signed-off-by: Dmitry V. Levin Signed-off-by: Junio C Hamano --- Documentation/git-archimport.txt | 2 +- Documentation/git-fetch-pack.txt | 2 +- Documentation/git-pack-redundant.txt | 2 +- Documentation/git-shell.txt | 2 +- Documentation/git-shortlog.txt | 2 +- Documentation/git-show-branch.txt | 6 +++--- Documentation/git-update-ref.txt | 2 +- Documentation/git-var.txt | 2 +- 8 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Documentation/git-archimport.txt b/Documentation/git-archimport.txt index 023d3ae7b9..5a13187a87 100644 --- a/Documentation/git-archimport.txt +++ b/Documentation/git-archimport.txt @@ -9,7 +9,7 @@ git-archimport - Import an Arch repository into git SYNOPSIS -------- [verse] -`git-archimport` [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir] +'git-archimport' [-h] [-v] [-o] [-a] [-f] [-T] [-D depth] [-t tempdir] [ ] DESCRIPTION diff --git a/Documentation/git-fetch-pack.txt b/Documentation/git-fetch-pack.txt index b507e9b648..913b75bb8d 100644 --- a/Documentation/git-fetch-pack.txt +++ b/Documentation/git-fetch-pack.txt @@ -8,7 +8,7 @@ git-fetch-pack - Receive missing objects from another repository. SYNOPSIS -------- -git-fetch-pack [-q] [-k] [--exec=] [:] [...] +'git-fetch-pack' [-q] [-k] [--exec=] [:] [...] DESCRIPTION ----------- diff --git a/Documentation/git-pack-redundant.txt b/Documentation/git-pack-redundant.txt index 2f4cc46510..a81cb97814 100644 --- a/Documentation/git-pack-redundant.txt +++ b/Documentation/git-pack-redundant.txt @@ -8,7 +8,7 @@ git-pack-redundant - Program used to find redundant pack files. SYNOPSIS -------- -'git-pack-redundant [ --verbose ] [ --alt-odb ] < --all | .pack filename ... >' +'git-pack-redundant' [ --verbose ] [ --alt-odb ] < --all | .pack filename ... > DESCRIPTION ----------- diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index 3f4d804cca..cc4266d83b 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -8,7 +8,7 @@ git-shell - Restricted login shell for GIT over SSH only SYNOPSIS -------- -'git-shell -c ' +'git-shell' -c DESCRIPTION ----------- diff --git a/Documentation/git-shortlog.txt b/Documentation/git-shortlog.txt index 65ca77fbf6..bf8db8bac6 100644 --- a/Documentation/git-shortlog.txt +++ b/Documentation/git-shortlog.txt @@ -8,7 +8,7 @@ git-shortlog - Summarize 'git log' output. SYNOPSIS -------- -'git-log --pretty=short | git shortlog' +git-log --pretty=short | 'git-shortlog' DESCRIPTION ----------- diff --git a/Documentation/git-show-branch.txt b/Documentation/git-show-branch.txt index 7b1a9c9875..e474cd0ba7 100644 --- a/Documentation/git-show-branch.txt +++ b/Documentation/git-show-branch.txt @@ -8,9 +8,9 @@ git-show-branch - Show branches and their commits. SYNOPSIS -------- [verse] -git-show-branch [--all] [--heads] [--tags] [--topo-order] [--current] - [--more= | --list | --independent | --merge-base] - [--no-name | --sha1-name] [ | ]... +'git-show-branch' [--all] [--heads] [--tags] [--topo-order] [--current] + [--more= | --list | --independent | --merge-base] + [--no-name | --sha1-name] [ | ]... DESCRIPTION ----------- diff --git a/Documentation/git-update-ref.txt b/Documentation/git-update-ref.txt index 69715aa061..475237f19e 100644 --- a/Documentation/git-update-ref.txt +++ b/Documentation/git-update-ref.txt @@ -7,7 +7,7 @@ git-update-ref - update the object name stored in a ref safely SYNOPSIS -------- -`git-update-ref` [] +'git-update-ref' [] DESCRIPTION ----------- diff --git a/Documentation/git-var.txt b/Documentation/git-var.txt index c22d34f5fb..90cb157be5 100644 --- a/Documentation/git-var.txt +++ b/Documentation/git-var.txt @@ -8,7 +8,7 @@ git-var - Print the git users identity SYNOPSIS -------- -git-var [ -l | ] +'git-var' [ -l | ] DESCRIPTION ----------- From 5fcab3d7db9bb29f3897a593da69d6ae83a405ef Mon Sep 17 00:00:00 2001 From: Ryan Anderson Date: Sun, 5 Mar 2006 21:43:53 -0500 Subject: [PATCH 11/15] annotate: Support annotation of files on other revisions. This is a bug fix, and cleans up one or two other things spotted during the course of tracking down the main bug here. [jc: the part that updates test-suite is split out to the next one. Also I dropped "use Data::Dumper;" which seemed leftover from debugging session.] Signed-off-by: Ryan Anderson Signed-off-by: Junio C Hamano --- git-annotate.perl | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/git-annotate.perl b/git-annotate.perl index b113def97b..feea0a2d81 100755 --- a/git-annotate.perl +++ b/git-annotate.perl @@ -99,7 +99,7 @@ while (my $bound = pop @stack) { } } push @revqueue, $head; -init_claim( defined $starting_rev ? $starting_rev : 'dirty'); +init_claim( defined $starting_rev ? $head : 'dirty'); unless (defined $starting_rev) { my $diff = open_pipe("git","diff","-R", "HEAD", "--",$filename) or die "Failed to call git diff to check for dirty state: $!"; @@ -345,6 +345,7 @@ sub git_cat_file { return () unless defined $rev && defined $filename; my $blob = git_ls_tree($rev, $filename); + die "Failed to find a blob for $filename in rev $rev\n" if !defined $blob; my $catfile = open_pipe("git","cat-file", "blob", $blob) or die "Failed to git-cat-file blob $blob (rev $rev, file $filename): " . $!; @@ -367,12 +368,13 @@ sub git_ls_tree { my ($mode, $type, $blob, $tfilename); while(<$lstree>) { + chomp; ($mode, $type, $blob, $tfilename) = split(/\s+/, $_, 4); last if ($tfilename eq $filename); } close($lstree); - return $blob if $filename eq $filename; + return $blob if ($tfilename eq $filename); die "git-ls-tree failed to find blob for $filename"; } From 92a903acfd0904e6dd6d18112428429938783d19 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 5 Mar 2006 22:07:37 -0800 Subject: [PATCH 12/15] annotate/blame tests updates. This rewrites the result check code a bit. The earlier one using awk was splitting columns at any whitespace, which confused lines attributed incorrectly to the merge made by the default author "A U Thor " with lines attributed to author "A". The latest test by Ryan to add the "starting from older commit" test is also included, with another older commit test. Signed-off-by: Junio C Hamano --- t/annotate-tests.sh | 81 ++++++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 37 deletions(-) diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index 54a4dfb9f4..d25a7a1e7a 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -1,6 +1,37 @@ # This file isn't used as a test script directly, instead it is # sourced from t8001-annotate.sh and t8001-blame.sh. +check_count () { + head= + case "$1" in -h) head="$2"; shift; shift ;; esac + $PROG file $head | perl -e ' + my %expect = (@ARGV); + my %count = (); + while () { + if (/^[0-9a-f]+\t\(([^\t]+)\t/) { + my $author = $1; + for ($author) { s/^\s*//; s/\s*$//; } + if (exists $expect{$author}) { + $count{$author}++; + } + } + } + my $bad = 0; + while (my ($author, $count) = each %count) { + my $ok; + if ($expect{$author} != $count) { + $bad = 1; + $ok = "bad"; + } + else { + $ok = "good"; + } + print STDERR "Author $author (expected $expect{$author}, attributed $count) $ok\n"; + } + exit($bad); + ' "$@" +} + test_expect_success \ 'prepare reference tree' \ 'echo "1A quick brown fox jumps over the" >file && @@ -10,7 +41,7 @@ test_expect_success \ test_expect_success \ 'check all lines blamed on A' \ - '[ $(git annotate file | awk "{print \$3}" | grep -c "A") == 2 ]' + 'check_count A 2' test_expect_success \ 'Setup new lines blamed on B' \ @@ -19,12 +50,8 @@ test_expect_success \ GIT_AUTHOR_NAME="B" git commit -a -m "Second."' test_expect_success \ - 'Two lines blamed on A' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "A") == 2 ]' - -test_expect_success \ - 'Two lines blamed on B' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "B") == 2 ]' + 'Two lines blamed on A, two on B' \ + 'check_count A 2 B 2' test_expect_success \ 'merge-setup part 1' \ @@ -34,16 +61,8 @@ test_expect_success \ GIT_AUTHOR_NAME="B1" git commit -a -m "Branch1-1"' test_expect_success \ - 'Two lines blamed on A' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^A$") == 2 ]' - -test_expect_success \ - 'Two lines blamed on B' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^B$") == 2 ]' - -test_expect_success \ - 'Two lines blamed on B1' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^B1$") == 2 ]' + 'Two lines blamed on A, two on B, two on B1' \ + 'check_count A 2 B 2 B1 2' test_expect_success \ 'merge-setup part 2' \ @@ -53,34 +72,22 @@ test_expect_success \ GIT_AUTHOR_NAME="B2" git commit -a -m "Branch2-1"' test_expect_success \ - 'Two lines blamed on A' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^A$") == 2 ]' - -test_expect_success \ - 'One line blamed on B' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^B$") == 1 ]' - -test_expect_success \ - 'One line blamed on B2' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^B2$") == 1 ]' - + 'Two lines blamed on A, one on B, one on B2' \ + 'check_count A 2 B 1 B2 1' test_expect_success \ 'merge-setup part 3' \ 'git pull . branch1' test_expect_success \ - 'Two lines blamed on A' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^A$") == 2 ]' + 'Two lines blamed on A, one on B, two on B1, one on B2' \ + 'check_count A 2 B 1 B1 2 B2 1' test_expect_success \ - 'One line blamed on B' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^B$") == 1 ]' + 'Annotating an old revision works' \ + 'check_count -h master A 2 B 2' test_expect_success \ - 'Two lines blamed on B1' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^B1$") == 2 ]' + 'Annotating an old revision works' \ + 'check_count -h master^ A 2' -test_expect_success \ - 'One line blamed on B2' \ - '[ $($PROG file | awk "{print \$3}" | grep -c "^B2$") == 1 ]' From 8ad02bc9649b0a69a0c09a23bd177a070b57af7d Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 5 Mar 2006 22:10:26 -0800 Subject: [PATCH 13/15] annotate-blame test: don't "source", but say "." Just I am old fashioned. Source inclusion in bourne shell is "." (dot), not "source" -- that's csh. [jc: yes I know bash groks it, but I am old fashioned.] Signed-off-by: Junio C Hamano --- t/t8001-annotate.sh | 2 +- t/t8002-blame.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/t/t8001-annotate.sh b/t/t8001-annotate.sh index 9e5a04b0f9..2496397da3 100755 --- a/t/t8001-annotate.sh +++ b/t/t8001-annotate.sh @@ -4,6 +4,6 @@ test_description='git-annotate' . ./test-lib.sh PROG='git annotate' -source ../annotate-tests.sh +. ../annotate-tests.sh test_done diff --git a/t/t8002-blame.sh b/t/t8002-blame.sh index 1036c54d30..9777393996 100755 --- a/t/t8002-blame.sh +++ b/t/t8002-blame.sh @@ -4,6 +4,6 @@ test_description='git-blame' . ./test-lib.sh PROG='git blame -c' -source ../annotate-tests.sh +. ../annotate-tests.sh test_done From ce5b6e711148d035478fcb18773a0abcef302d7e Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 5 Mar 2006 22:37:15 -0800 Subject: [PATCH 14/15] annotate-blame test: add evil merge. Signed-off-by: Junio C Hamano --- t/annotate-tests.sh | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/t/annotate-tests.sh b/t/annotate-tests.sh index d25a7a1e7a..8cb32e156b 100644 --- a/t/annotate-tests.sh +++ b/t/annotate-tests.sh @@ -91,3 +91,12 @@ test_expect_success \ 'Annotating an old revision works' \ 'check_count -h master^ A 2' +test_expect_success \ + 'merge-setup part 4' \ + 'echo "evil merge." >>file && + EDITOR=: git commit -a --amend' + +test_expect_success \ + 'Two lines blamed on A, one on B, two on B1, one on B2, one on A U Thor' \ + 'check_count A 2 B 1 B1 2 B2 1 "A U Thor" 1' + From e920b5655719bee9c98a3d7d3b05ac6e8cf9d176 Mon Sep 17 00:00:00 2001 From: Francis Daly Date: Sun, 5 Mar 2006 23:13:36 +0000 Subject: [PATCH 15/15] Tweak asciidoc output to work with broken docbook-xsl docbook-xsl v1.68 incorrectly converts "" from docbook to manpage by not rendering it verbatim. v1.69 handles it correctly, but not many current popular distributions ship with it. asciidoc by default converts "listingblock" to "". This change causes asciidoc in git to convert "listingblock" to "", which both old and new docbook-xsl handle correctly. The difference can be seen in any manpage which includes a multi-line example, such as git-branch. [jc: the original patch was an disaster for html backends, so I made it apply only to docbook backends. ] Signed-off-by: Junio C Hamano --- Documentation/asciidoc.conf | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Documentation/asciidoc.conf b/Documentation/asciidoc.conf index fa0877d483..7ce71510de 100644 --- a/Documentation/asciidoc.conf +++ b/Documentation/asciidoc.conf @@ -18,6 +18,16 @@ ifdef::backend-docbook[] {0#} endif::backend-docbook[] +ifdef::backend-docbook[] +# "unbreak" docbook-xsl v1.68 for manpages. v1.69 works with or without this. +[listingblock] +{title} + +| + +{title#} +endif::backend-docbook[] + ifdef::backend-xhtml11[] [gitlink-inlinemacro] {target}{0?({0})}