From adb7b5fc86d96fc2baf5a5c0ce12fb581b3ad275 Mon Sep 17 00:00:00 2001 From: Martin Koegler Date: Tue, 1 May 2007 11:47:55 +0200 Subject: [PATCH 01/28] Fix compilation of test-delta The code used write_in_full() without pulling its declarations from the header file. When header is included, usage[] collides with usage() function. Signed-off-by: Martin Koegler Signed-off-by: Junio C Hamano --- test-delta.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/test-delta.c b/test-delta.c index 16595ef0a9..3d885ff37e 100644 --- a/test-delta.c +++ b/test-delta.c @@ -10,8 +10,9 @@ #include "git-compat-util.h" #include "delta.h" +#include "cache.h" -static const char usage[] = +static const char usage_str[] = "test-delta (-d|-p) "; int main(int argc, char *argv[]) @@ -22,7 +23,7 @@ int main(int argc, char *argv[]) unsigned long from_size, data_size, out_size; if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) { - fprintf(stderr, "Usage: %s\n", usage); + fprintf(stderr, "Usage: %s\n", usage_str); return 1; } From 775477aa1da94cb9fb9b9afdc217231a0cd42ac1 Mon Sep 17 00:00:00 2001 From: Johannes Schindelin Date: Tue, 1 May 2007 23:42:44 +0200 Subject: [PATCH 02/28] Teach import-tars about GNU tar's @LongLink extension. This extension allows GNU tar to process file names in excess of the 100 characters defined by the original tar standard. It does this by faking a file, named '././@LongLink' containing the true file name, and then adding the file with a truncated name. The idea is that tar without this extension will write out a file with the long file name, and write the contents into a file with truncated name. Unfortunately, GNU tar does a lousy job at times. When truncating results in a _directory_ name, it will happily use _that_ as a truncated name for the file. An example where this actually happens is gcc-4.1.2, where the full path of the file WeThrowThisExceptionHelper.java truncates _exactly_ before the basename. So, we have to support that ad-hoc extension. This bug was noticed by Chris Riddoch on IRC. Signed-off-by: Johannes Schindelin Signed-off-by: Shawn O. Pearce --- contrib/fast-import/import-tars.perl | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/contrib/fast-import/import-tars.perl b/contrib/fast-import/import-tars.perl index 82a90429c8..e46492048c 100755 --- a/contrib/fast-import/import-tars.perl +++ b/contrib/fast-import/import-tars.perl @@ -52,6 +52,25 @@ foreach my $tar_file (@ARGV) Z8 Z1 Z100 Z6 Z2 Z32 Z32 Z8 Z8 Z*', $_; last unless $name; + if ($name eq '././@LongLink') { + # GNU tar extension + if (read(I, $_, 512) != 512) { + die ('Short archive'); + } + $name = unpack 'Z257', $_; + next unless $name; + + my $dummy; + if (read(I, $_, 512) != 512) { + die ('Short archive'); + } + ($dummy, $mode, $uid, $gid, $size, $mtime, + $chksum, $typeflag, $linkname, $magic, + $version, $uname, $gname, $devmajor, $devminor, + $prefix) = unpack 'Z100 Z8 Z8 Z8 Z12 Z12 + Z8 Z1 Z100 Z6 + Z2 Z32 Z32 Z8 Z8 Z*', $_; + } next if $name =~ m{/\z}; $mode = oct $mode; $size = oct $size; From 8b0eca7c7b73d0dc5d49f400a878d9b781ec4bec Mon Sep 17 00:00:00 2001 From: "Dana L. How" Date: Wed, 2 May 2007 12:13:14 -0400 Subject: [PATCH 03/28] Create pack-write.c for common pack writing code Include a generalized fixup_pack_header_footer() in this new file. Needed by git-repack --max-pack-size feature in a later patchset. [sp: Moved close(pack_fd) to callers, to support index-pack, and changed name to better indicate it is for packfiles.] Signed-off-by: Dana L. How Signed-off-by: Shawn O. Pearce --- Makefile | 4 ++-- fast-import.c | 40 +++------------------------------------- pack-write.c | 39 +++++++++++++++++++++++++++++++++++++++ pack.h | 1 + 4 files changed, 45 insertions(+), 39 deletions(-) create mode 100644 pack-write.c diff --git a/Makefile b/Makefile index 2fea115919..e0a1308c09 100644 --- a/Makefile +++ b/Makefile @@ -301,8 +301,8 @@ LIB_OBJS = \ interpolate.o \ lockfile.o \ patch-ids.o \ - object.o pack-check.o patch-delta.o path.o pkt-line.o sideband.o \ - reachable.o reflog-walk.o \ + object.o pack-check.o pack-write.o patch-delta.o path.o pkt-line.o \ + sideband.o reachable.o reflog-walk.o \ quote.o read-cache.o refs.o run-command.o dir.o object-refs.o \ server-info.o setup.o sha1_file.o sha1_name.o strbuf.o \ tag.o tree.o usage.o config.o environment.o ctype.o copy.o \ diff --git a/fast-import.c b/fast-import.c index b4cbcd9011..3a2d5ed8e6 100644 --- a/fast-import.c +++ b/fast-import.c @@ -651,42 +651,6 @@ static void start_packfile(void) all_packs[pack_id] = p; } -static void fixup_header_footer(void) -{ - static const int buf_sz = 128 * 1024; - int pack_fd = pack_data->pack_fd; - SHA_CTX c; - struct pack_header hdr; - char *buf; - - if (lseek(pack_fd, 0, SEEK_SET) != 0) - die("Failed seeking to start: %s", strerror(errno)); - if (read_in_full(pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr)) - die("Unable to reread header of %s", pack_data->pack_name); - if (lseek(pack_fd, 0, SEEK_SET) != 0) - die("Failed seeking to start: %s", strerror(errno)); - hdr.hdr_entries = htonl(object_count); - write_or_die(pack_fd, &hdr, sizeof(hdr)); - - SHA1_Init(&c); - SHA1_Update(&c, &hdr, sizeof(hdr)); - - buf = xmalloc(buf_sz); - for (;;) { - ssize_t n = xread(pack_fd, buf, buf_sz); - if (!n) - break; - if (n < 0) - die("Failed to checksum %s", pack_data->pack_name); - SHA1_Update(&c, buf, n); - } - free(buf); - - SHA1_Final(pack_data->sha1, &c); - write_or_die(pack_fd, pack_data->sha1, sizeof(pack_data->sha1)); - close(pack_fd); -} - static int oecmp (const void *a_, const void *b_) { struct object_entry *a = *((struct object_entry**)a_); @@ -802,7 +766,9 @@ static void end_packfile(void) struct branch *b; struct tag *t; - fixup_header_footer(); + fixup_pack_header_footer(pack_data->pack_fd, pack_data->sha1, + pack_data->pack_name, object_count); + close(pack_data->pack_fd); idx_name = keep_pack(create_index()); /* Register the packfile with core git's machinary. */ diff --git a/pack-write.c b/pack-write.c new file mode 100644 index 0000000000..de72f44dc8 --- /dev/null +++ b/pack-write.c @@ -0,0 +1,39 @@ +#include "cache.h" +#include "pack.h" + +void fixup_pack_header_footer(int pack_fd, + unsigned char *pack_file_sha1, + const char *pack_name, + uint32_t object_count) +{ + static const int buf_sz = 128 * 1024; + SHA_CTX c; + struct pack_header hdr; + char *buf; + + if (lseek(pack_fd, 0, SEEK_SET) != 0) + die("Failed seeking to start: %s", strerror(errno)); + if (read_in_full(pack_fd, &hdr, sizeof(hdr)) != sizeof(hdr)) + die("Unable to reread header of %s: %s", pack_name, strerror(errno)); + if (lseek(pack_fd, 0, SEEK_SET) != 0) + die("Failed seeking to start: %s", strerror(errno)); + hdr.hdr_entries = htonl(object_count); + write_or_die(pack_fd, &hdr, sizeof(hdr)); + + SHA1_Init(&c); + SHA1_Update(&c, &hdr, sizeof(hdr)); + + buf = xmalloc(buf_sz); + for (;;) { + size_t n = xread(pack_fd, buf, buf_sz); + if (!n) + break; + if (n < 0) + die("Failed to checksum %s: %s", pack_name, strerror(errno)); + SHA1_Update(&c, buf, n); + } + free(buf); + + SHA1_Final(pack_file_sha1, &c); + write_or_die(pack_fd, pack_file_sha1, 20); +} diff --git a/pack.h b/pack.h index d4d412ccbb..d667fb8d5a 100644 --- a/pack.h +++ b/pack.h @@ -44,6 +44,7 @@ struct pack_idx_header { extern int verify_pack(struct packed_git *, int); +extern void fixup_pack_header_footer(int, unsigned char *, const char *, uint32_t); #define PH_ERROR_EOF (-1) #define PH_ERROR_PACK_SIGNATURE (-2) From cbc6bdab08af239b5a6477e7e6db16a766ec4986 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 2 May 2007 12:14:15 -0400 Subject: [PATCH 04/28] Reuse fixup_pack_header_footer in index-pack Now that fast-import is using a "library function" to handle correcting its packfile's object count and trailing SHA-1 we should reuse the same function in index-pack, to reduce the size of the code we must maintain. Signed-off-by: Shawn O. Pearce --- index-pack.c | 34 ++-------------------------------- 1 file changed, 2 insertions(+), 32 deletions(-) diff --git a/index-pack.c b/index-pack.c index 824004f9a2..b9da19f55b 100644 --- a/index-pack.c +++ b/index-pack.c @@ -602,37 +602,6 @@ static void fix_unresolved_deltas(int nr_unresolved) free(sorted_by_pos); } -static void readjust_pack_header_and_sha1(unsigned char *sha1) -{ - struct pack_header hdr; - SHA_CTX ctx; - int size; - - /* Rewrite pack header with updated object number */ - if (lseek(output_fd, 0, SEEK_SET) != 0) - die("cannot seek back: %s", strerror(errno)); - if (read_in_full(output_fd, &hdr, sizeof(hdr)) != sizeof(hdr)) - die("cannot read pack header back: %s", strerror(errno)); - hdr.hdr_entries = htonl(nr_objects); - if (lseek(output_fd, 0, SEEK_SET) != 0) - die("cannot seek back: %s", strerror(errno)); - write_or_die(output_fd, &hdr, sizeof(hdr)); - if (lseek(output_fd, 0, SEEK_SET) != 0) - die("cannot seek back: %s", strerror(errno)); - - /* Recompute and store the new pack's SHA1 */ - SHA1_Init(&ctx); - do { - unsigned char *buf[4096]; - size = xread(output_fd, buf, sizeof(buf)); - if (size < 0) - die("cannot read pack data back: %s", strerror(errno)); - SHA1_Update(&ctx, buf, size); - } while (size > 0); - SHA1_Final(sha1, &ctx); - write_or_die(output_fd, sha1, 20); -} - static uint32_t index_default_version = 1; static uint32_t index_off32_limit = 0x7fffffff; @@ -963,7 +932,8 @@ int main(int argc, char **argv) fprintf(stderr, "%d objects were added to complete this thin pack.\n", nr_objects - nr_objects_initial); } - readjust_pack_header_and_sha1(sha1); + fixup_pack_header_footer(output_fd, sha1, + curr_pack, nr_objects); } if (nr_deltas != nr_resolved_deltas) die("pack has %d unresolved deltas", From b3431bc603df74cfe2da56e9a5c3f60327dd56b9 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Wed, 2 May 2007 12:59:55 -0400 Subject: [PATCH 05/28] Don't use seq in tests, not everyone has it For example Mac OS X lacks the seq command. So we cannot use it there. A good old while loop works just as good. Signed-off-by: Shawn O. Pearce --- t/t5302-pack-index.sh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/t/t5302-pack-index.sh b/t/t5302-pack-index.sh index 6902fc6d48..4d06eca6a5 100755 --- a/t/t5302-pack-index.sh +++ b/t/t5302-pack-index.sh @@ -10,11 +10,14 @@ test_expect_success \ 'setup' \ 'rm -rf .git git-init && - for i in `seq -w 100` + i=1 && + while test $i -le 100 do + i=`printf '%03i' $i` echo $i >file_$i && test-genrandom "$i" 8192 >>file_$i && - git-update-index --add file_$i || return 1 + git-update-index --add file_$i && + i=`expr $i + 1` || return 1 done && { echo 101 && test-genrandom 100 8192; } >file_101 && git-update-index --add file_101 && From a7da9adb1ff4e2a378fdb2eb486a83ee2d68c847 Mon Sep 17 00:00:00 2001 From: Frank Lichtenheld Date: Wed, 2 May 2007 02:43:14 +0200 Subject: [PATCH 06/28] cvsserver: Handle re-added files correctly We can't unconditionally assign revision 1.1 to newly added files. In case the file did exist in the past and was deleted we need to honor the old revision number. Signed-off-by: Frank Lichtenheld Signed-off-by: Junio C Hamano --- git-cvsserver.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-cvsserver.perl b/git-cvsserver.perl index 25816c5a21..3501c1bc3a 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -2454,7 +2454,7 @@ sub update #$log->debug("ADDED $name"); $head->{$name} = { name => $name, - revision => 1, + revision => $head->{$name}{revision} ? $head->{$name}{revision}+1 : 1, filehash => $hash, commithash => $commit->{hash}, modified => $commit->{date}, From 50acc58914bf02217e55fdd739a844f2bfc45410 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 2 May 2007 23:58:14 -0700 Subject: [PATCH 07/28] blame: use .mailmap unconditionally There really isn't any point in turning off .mailmap. The number of mailmap lookups are bounded by number of lines in the target file, and the real blame processing is much more expensive. If it turns out to be too costly, we should optimize the mailmap lookup itself, instead of avoiding the call. If the author information of commits of the project are relatively clean, .mailmap would have only small number of entries, and the overhead of looking it up will not be high. On the other hand, if the author information is really screwed up that a good .mailmap needs to be maintained to run shortlog, giving uncleaned names in blame output is not helpful at all either. Signed-off-by: Junio C Hamano --- builtin-blame.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index 3442d282aa..6d6a577d68 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -20,13 +20,12 @@ #include "mailmap.h" static char blame_usage[] = -"git-blame [-c] [-b] [-l] [--root] [-x] [-t] [-f] [-n] [-s] [-p] [-L n,m] [-S ] [-M] [-C] [-C] [--contents ] [--incremental] [commit] [--] file\n" +"git-blame [-c] [-b] [-l] [--root] [-t] [-f] [-n] [-s] [-p] [-L n,m] [-S ] [-M] [-C] [-C] [--contents ] [--incremental] [commit] [--] file\n" " -c Use the same output mode as git-annotate (Default: off)\n" " -b Show blank SHA-1 for boundary commits (Default: off)\n" " -l Show long commit SHA1 (Default: off)\n" " --root Do not treat root commits as boundaries (Default: off)\n" " -t Show raw timestamp (Default: off)\n" -" -x Do not use .mailmap file\n" " -f, --show-name Show original filename (Default: auto)\n" " -n, --show-number Show original linenumber (Default: off)\n" " -s Suppress author name and timestamp (Default: off)\n" @@ -46,7 +45,6 @@ static int show_root; static int blank_boundary; static int incremental; static int cmd_is_annotate; -static int no_mailmap; static struct path_list mailmap; #ifndef DEBUG @@ -2173,9 +2171,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix) else if (!strcmp("-p", arg) || !strcmp("--porcelain", arg)) output_option |= OUTPUT_PORCELAIN; - else if (!strcmp("-x", arg) || - !strcmp("--no-mailmap", arg)) - no_mailmap = 1; else if (!strcmp("--", arg)) { seen_dashdash = 1; i++; @@ -2375,8 +2370,7 @@ int cmd_blame(int argc, const char **argv, const char *prefix) die("reading graft file %s failed: %s", revs_file, strerror(errno)); - if (!no_mailmap) - read_mailmap(&mailmap, ".mailmap", NULL); + read_mailmap(&mailmap, ".mailmap", NULL); assign_blame(&sb, &revs, opt); From 9cf04301b182c4c57d62ea63554d109db613f9d3 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Wed, 2 May 2007 14:53:23 +0200 Subject: [PATCH 08/28] http-fetch: Disable use of curl multi support for libcurl < 7.16. curl_multi_remove_handle() is broken in libcurl < 7.16, in that it doesn't correctly update the active handles count when a request is aborted. This causes the transfer to hang forever waiting for the handle count to become less than the number of active requests. Signed-off-by: Alexandre Julliard Signed-off-by: Junio C Hamano --- http.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/http.h b/http.h index 324fcf4f54..69b6b667d9 100644 --- a/http.h +++ b/http.h @@ -6,7 +6,7 @@ #include #include -#if LIBCURL_VERSION_NUM >= 0x070908 +#if LIBCURL_VERSION_NUM >= 0x071000 #define USE_CURL_MULTI #define DEFAULT_MAX_REQUESTS 5 #endif From cdda666201710dcf50d7ebee804aac65fdec32fd Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Thu, 3 May 2007 13:00:43 -0700 Subject: [PATCH 09/28] diff.c: fix "size cache" handling. We broke the size-cache handling when we changed the function signature of sha1_object_info() in 21666f1a. We obviously wanted to cache the size we obtained when sha1_object_info() succeeded, not when it failed. Signed-off-by: Junio C Hamano --- diff.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/diff.c b/diff.c index d8f9242ea8..b28933f870 100644 --- a/diff.c +++ b/diff.c @@ -1468,14 +1468,15 @@ int diff_populate_filespec(struct diff_filespec *s, int size_only) enum object_type type; struct sha1_size_cache *e; + if (size_only && use_size_cache && + (e = locate_size_cache(s->sha1, 1, 0)) != NULL) { + s->size = e->size; + return 0; + } + if (size_only) { - e = locate_size_cache(s->sha1, 1, 0); - if (e) { - s->size = e->size; - return 0; - } type = sha1_object_info(s->sha1, &s->size); - if (type < 0) + if (use_size_cache && 0 < type) locate_size_cache(s->sha1, 0, s->size); } else { From 5094102e13640d7559a02fd7c77b44dc9254cbbb Mon Sep 17 00:00:00 2001 From: Daniel Barkalow Date: Wed, 2 May 2007 22:49:41 -0400 Subject: [PATCH 10/28] Make xstrndup common This also improves the implementation to match how strndup is specified (by GNU): if the length given is longer than the string, only the string's length is allocated and copied, but the string need not be null-terminated if it is at least as long as the given length. Signed-off-by: Daniel Barkalow Signed-off-by: Junio C Hamano --- commit.c | 8 -------- git-compat-util.h | 13 +++++++++++++ 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/commit.c b/commit.c index 754d1b8a0b..eb911f44d7 100644 --- a/commit.c +++ b/commit.c @@ -720,14 +720,6 @@ static char *logmsg_reencode(const struct commit *commit, return out; } -static char *xstrndup(const char *text, int len) -{ - char *result = xmalloc(len + 1); - memcpy(result, text, len); - result[len] = '\0'; - return result; -} - static void fill_person(struct interp *table, const char *msg, int len) { int start, end, tz = 0; diff --git a/git-compat-util.h b/git-compat-util.h index e3cf3703bb..bd93b62578 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -189,6 +189,19 @@ static inline void *xmalloc(size_t size) return ret; } +static inline char *xstrndup(const char *str, size_t len) +{ + char *p; + + p = memchr(str, '\0', len); + if (p) + len = p - str; + p = xmalloc(len + 1); + memcpy(p, str, len); + p[len] = '\0'; + return p; +} + static inline void *xrealloc(void *ptr, size_t size) { void *ret = realloc(ptr, size); From 5318f69812b3a06326524852d965e6a79fa52f85 Mon Sep 17 00:00:00 2001 From: Bryan Larsen Date: Thu, 3 May 2007 18:58:56 -0400 Subject: [PATCH 11/28] Allow PERL_PATH="/usr/bin/env perl" There is a mechanism PERL_PATH in the Makefile to specify path to Perl binary, but sometimes it is convenient to let 'env' figure out where Perl comes from, with PERL_PATH="/usr/bin/env perl". Allowing this would make things easier to MacPorts, where we wish to work with the MacPorts perl if it is installed, but fall back to the system perl if it isn't. Signed-off-by: Bryan Larsen Signed-off-by: Junio C Hamano --- perl/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/perl/Makefile b/perl/Makefile index 17d004e5a0..0d695fd2f3 100644 --- a/perl/Makefile +++ b/perl/Makefile @@ -33,7 +33,7 @@ $(makfile): ../GIT-CFLAGS Makefile echo ' echo $(instdir_SQ)' >> $@ else $(makfile): Makefile.PL ../GIT-CFLAGS - '$(PERL_PATH_SQ)' $< PREFIX='$(prefix_SQ)' + $(PERL_PATH) $< PREFIX='$(prefix_SQ)' endif # this is just added comfort for calling make directly in perl dir From e4e92b3f4bead3ee17164db35a44f8904eac9104 Mon Sep 17 00:00:00 2001 From: Arjen Laarhoven Date: Thu, 3 May 2007 20:29:15 +0200 Subject: [PATCH 12/28] Document 'opendiff' value in config.txt and git-mergetool.txt Signed-off-by: Arjen Laarhoven Signed-off-by: Junio C Hamano --- Documentation/config.txt | 2 +- Documentation/git-mergetool.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/config.txt b/Documentation/config.txt index 7e41ca6a0d..a7daa08731 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -490,7 +490,7 @@ merge.summary:: merge.tool:: Controls which merge resolution program is used by gitlink:git-mergetool[l]. Valid values are: "kdiff3", "tkdiff", - "meld", "xxdiff", "emerge", "vimdiff" + "meld", "xxdiff", "emerge", "vimdiff", and "opendiff" merge.verbosity:: Controls the amount of output shown by the recursive merge diff --git a/Documentation/git-mergetool.txt b/Documentation/git-mergetool.txt index 34288fe08b..add01e855a 100644 --- a/Documentation/git-mergetool.txt +++ b/Documentation/git-mergetool.txt @@ -25,7 +25,7 @@ OPTIONS -t or --tool=:: Use the merge resolution program specified by . Valid merge tools are: - kdiff3, tkdiff, meld, xxdiff, emerge, and vimdiff. + kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, and opendiff + If a merge resolution program is not specified, 'git mergetool' will use the configuration variable merge.tool. If the From c256acb8fbd0ac1dddb6ec39aa9b3c816493122c Mon Sep 17 00:00:00 2001 From: Bryan Larsen Date: Wed, 2 May 2007 17:53:23 -0400 Subject: [PATCH 13/28] posix compatibility for t4200 Fix t4200 so that it also works on OS X by not relying on gnu extensions to sed. Signed-off-by: Bryan Larsen Signed-off-by: Junio C Hamano --- t/t4200-rerere.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/t4200-rerere.sh b/t/t4200-rerere.sh index 6ba63d7173..c64ebbb2e9 100755 --- a/t/t4200-rerere.sh +++ b/t/t4200-rerere.sh @@ -44,7 +44,7 @@ mkdir .git/rr-cache test_expect_failure 'conflicting merge' 'git pull . first' -sha1=$(sed -e 's/\t.*//' .git/rr-cache/MERGE_RR) +sha1=$(sed -e 's/ .*//' .git/rr-cache/MERGE_RR) rr=.git/rr-cache/$sha1 test_expect_success 'recorded preimage' "grep ======= $rr/preimage" From e3ad95a8be82663d27cb501eaf9bad86a30f9cda Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ismail=20D=C3=B6nmez?= Date: Wed, 2 May 2007 00:12:13 +0300 Subject: [PATCH 14/28] gitweb: use decode_utf8 directly Using decode() tries to decode data that is already UTF-8 and borks, but decode_utf8 from Encode.pm has a built-in safety against that. Signed-off-by: Junio C Hamano --- gitweb/gitweb.perl | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl index 45ac9d7121..12c2e6685e 100755 --- a/gitweb/gitweb.perl +++ b/gitweb/gitweb.perl @@ -560,12 +560,6 @@ sub validate_refname { return $input; } -# very thin wrapper for decode("utf8", $str, Encode::FB_DEFAULT); -sub to_utf8 { - my $str = shift; - return decode("utf8", $str, Encode::FB_DEFAULT); -} - # quote unsafe chars, but keep the slash, even when it's not # correct, but quoted slashes look too horrible in bookmarks sub esc_param { @@ -590,7 +584,7 @@ sub esc_html ($;%) { my $str = shift; my %opts = @_; - $str = to_utf8($str); + $str = decode_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -604,7 +598,7 @@ sub esc_path { my $str = shift; my %opts = @_; - $str = to_utf8($str); + $str = decode_utf8($str); $str = $cgi->escapeHTML($str); if ($opts{'-nbsp'}) { $str =~ s/ / /g; @@ -887,7 +881,7 @@ sub format_subject_html { if (length($short) < length($long)) { return $cgi->a({-href => $href, -class => "list subject", - -title => to_utf8($long)}, + -title => decode_utf8($long)}, esc_html($short) . $extra); } else { return $cgi->a({-href => $href, -class => "list subject"}, @@ -1104,7 +1098,7 @@ sub git_get_projects_list { if (check_export_ok("$projectroot/$path")) { my $pr = { path => $path, - owner => to_utf8($owner), + owner => decode_utf8($owner), }; push @list, $pr } @@ -1133,7 +1127,7 @@ sub git_get_project_owner { $pr = unescape($pr); $ow = unescape($ow); if ($pr eq $project) { - $owner = to_utf8($ow); + $owner = decode_utf8($ow); last; } } @@ -1607,7 +1601,7 @@ sub get_file_owner { } my $owner = $gcos; $owner =~ s/[,;].*$//; - return to_utf8($owner); + return decode_utf8($owner); } ## ...................................................................... @@ -1690,7 +1684,7 @@ sub git_header_html { my $title = "$site_name"; if (defined $project) { - $title .= " - " . to_utf8($project); + $title .= " - " . decode_utf8($project); if (defined $action) { $title .= "/$action"; if (defined $file_name) { @@ -1963,7 +1957,7 @@ sub git_print_page_path { print "
"; print $cgi->a({-href => href(action=>"tree", hash_base=>$hb), - -title => 'tree root'}, to_utf8("[$project]")); + -title => 'tree root'}, decode_utf8("[$project]")); print " / "; if (defined $name) { my @dirname = split '/', $name; @@ -2578,7 +2572,7 @@ sub git_project_list_body { ($pr->{'age'}, $pr->{'age_string'}) = @aa; if (!defined $pr->{'descr'}) { my $descr = git_get_project_description($pr->{'path'}) || ""; - $pr->{'descr_long'} = to_utf8($descr); + $pr->{'descr_long'} = decode_utf8($descr); $pr->{'descr'} = chop_str($descr, 25, 5); } if (!defined $pr->{'owner'}) { @@ -3610,7 +3604,7 @@ sub git_snapshot { $hash = git_get_head_hash($project); } - my $filename = to_utf8(basename($project)) . "-$hash.tar.$suffix"; + my $filename = decode_utf8(basename($project)) . "-$hash.tar.$suffix"; print $cgi->header( -type => "application/$ctype", From ff06c743dcd7f451381b41aeac4288179eaec428 Mon Sep 17 00:00:00 2001 From: "Shawn O. Pearce" Date: Tue, 1 May 2007 02:08:23 -0400 Subject: [PATCH 15/28] Improve request-pull to handle non-rebased branches This is actually a few different changes to request-pull, making it slightly smarter: 1) Minor cleanup of revision->base variable names, making it follow the head/headrev naming convention that is already in use. 2) Compute the merge-base between the two revisions upfront and reuse that selected merge-base to create the diffstat. 3) Refuse to generate a pull request for branches that have no existing relationship. These aren't very common and would mess up our diffstat generation. 4) Disable the PAGER when running shortlog and diff, as these would otherwise activate the pager for each command when git-request-pull is run on a tty. Instead users can get the entire output paged (if desired) using `git -p request-pull`. 5) Use shortlog rather than `git log | git shortlog` now that recent shortlog versions are able to run the revision listing internally. 6) Attempt to resolve the input URL using the user's configured remotes. This is useful if the URL you want the recipient to see is also the one you used to push your changes. If not a config-file remote could easily be setup for the public URL and request-pull could be passed that name instead. 7) Automatically guess and include the remote branch name in the body of the message. We list the branch name immediately after the URL, making it easy for the recipient to copy and paste the entire line onto a `git pull` command line. Rumor has it Linus likes this format, for exactly that reason. If multiple branches at the remote match $headrev we take the first one returned by peek-remote and assume it is suitable. If no branches are available we warn the user about the problem, but insert a static string that is not a valid branch name and would be obvious to anyone reading the message as being totally incorrect. This allows users to still generate a template message without network access (for example) and hand-correct the bits that cannot be verified. Signed-off-by: Shawn O. Pearce Signed-off-by: Junio C Hamano --- git-request-pull.sh | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/git-request-pull.sh b/git-request-pull.sh index 4eacc3a059..ba577d4ce1 100755 --- a/git-request-pull.sh +++ b/git-request-pull.sh @@ -9,25 +9,48 @@ LONG_USAGE='Summarizes the changes since to the standard output, and includes in the message generated.' SUBDIRECTORY_OK='Yes' . git-sh-setup +. git-parse-remote -revision=$1 +base=$1 url=$2 head=${3-HEAD} -[ "$revision" ] || usage +[ "$base" ] || usage [ "$url" ] || usage -baserev=`git-rev-parse --verify "$revision"^0` && +baserev=`git-rev-parse --verify "$base"^0` && headrev=`git-rev-parse --verify "$head"^0` || exit +merge_base=`git merge-base $baserev $headrev` || +die "fatal: No commits in common between $base and $head" + +url="`get_remote_url "$url"`" +branch=`git peek-remote "$url" \ + | sed -n -e "/^$headrev refs.heads./{ + s/^.* refs.heads.// + p + q + }"` +if [ -z "$branch" ]; then + echo "warn: No branch of $url is at:" >&2 + git log --max-count=1 --pretty='format:warn: %h: %s' $headrev >&2 + echo "warn: Are you sure you pushed $head there?" >&2 + echo >&2 + echo >&2 + branch=..BRANCH.NOT.VERIFIED.. + status=1 +fi + +PAGER= +export PAGER echo "The following changes since commit $baserev:" -git log --max-count=1 --pretty=short "$baserev" | -git-shortlog | sed -e 's/^\(.\)/ \1/' +git shortlog --max-count=1 $baserev | sed -e 's/^\(.\)/ \1/' -echo "are found in the git repository at:" +echo "are available in the git repository at:" echo -echo " $url" +echo " $url $branch" echo -git log $baserev..$headrev | git-shortlog ; -git diff -M --stat --summary $baserev..$headrev +git shortlog ^$baserev $headrev +git diff -M --stat --summary $merge_base $headrev +exit $status From 86b9e017e485a4e56fb8f096cb9094c415483118 Mon Sep 17 00:00:00 2001 From: Jonas Fonseca Date: Tue, 1 May 2007 09:24:59 +0200 Subject: [PATCH 16/28] git-tag(1): -v option is a subcommand; fix code block When the -v is passed, git-tag will exit after it is processed like it does with the -d and -l options. Additionally, missing code block caused wrong rendering of an option example. Signed-off-by: Jonas Fonseca Signed-off-by: Junio C Hamano --- Documentation/git-tag.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Documentation/git-tag.txt b/Documentation/git-tag.txt index 70235e8ddb..4e3e02756c 100644 --- a/Documentation/git-tag.txt +++ b/Documentation/git-tag.txt @@ -9,9 +9,10 @@ git-tag - Create, list, delete or verify a tag object signed with GPG SYNOPSIS -------- [verse] -'git-tag' [-a | -s | -u ] [-f | -v] [-m | -F ] [] +'git-tag' [-a | -s | -u ] [-f] [-m | -F ] [] 'git-tag' -d ... 'git-tag' -l [] +'git-tag' -v DESCRIPTION ----------- @@ -77,8 +78,10 @@ committer identity (of the form "Your Name ") to find a key. If you want to use a different default key, you can specify it in the repository configuration as follows: +------------------------------------- [user] signingkey = +------------------------------------- DISCUSSION From cc1793e2cef20a06aed6d8987c3361e7fbd09305 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Hasselstr=C3=B6m?= Date: Fri, 4 May 2007 09:03:22 +0200 Subject: [PATCH 17/28] Fix markup in git-svn man page MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some of the existing markup was just plain broken, and some subcommand options weren't indented properly. Signed-off-by: Karl Hasselström Signed-off-by: Junio C Hamano --- Documentation/git-svn.txt | 32 +++++++++++++------------------- 1 file changed, 13 insertions(+), 19 deletions(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 62d7ef8be4..820a2c308e 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -38,32 +38,30 @@ COMMANDS argument. Normally this command initializes the current directory. --T:: ---trunk=:: --t:: ---tags=:: --b:: ---branches=:: +-T;; +--trunk=;; +-t;; +--tags=;; +-b;; +--branches=;; These are optional command-line options for init. Each of these flags can point to a relative repository path (--tags=project/tags') or a full url (--tags=https://foo.org/project/tags) - ---no-metadata:: +--no-metadata;; Set the 'noMetadata' option in the [svn-remote] config. ---use-svm-props:: +--use-svm-props;; Set the 'useSvmProps' option in the [svn-remote] config. ---use-svnsync-props:: +--use-svnsync-props;; Set the 'useSvnsyncProps' option in the [svn-remote] config. ---rewrite-root=:: +--rewrite-root=;; Set the 'rewriteRoot' option in the [svn-remote] config. ---username=:: +--username=;; For transports that SVN handles authentication for (http, https, and plain svn), specify the username. For other transports (eg svn+ssh://), you must include the username in the URL, eg svn+ssh://foo@svn.bar.com/project - ---prefix=:: +--prefix=;; This allows one to specify a prefix which is prepended to the names of remotes if trunk/branches/tags are specified. The prefix does not automatically include a @@ -73,7 +71,6 @@ COMMANDS repository. 'fetch':: - Fetch unfetched revisions from the Subversion remote we are tracking. The name of the [svn-remote "..."] section in the .git/config file may be specified as an optional command-line @@ -104,14 +101,11 @@ accepts. However '--fetch-all' only fetches from the current Like 'git-rebase'; this requires that the working tree be clean and have no uncommitted changes. -+ --- + -l;; --local;; Do not fetch remotely; only run 'git-rebase' against the last fetched commit from the upstream SVN. --- -+ 'dcommit':: Commit each diff from a specified head directly to the SVN From 171af11082d41f8e7a678e1e1a4ec6f610d01cf4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karl=20Hasselstr=C3=B6m?= Date: Thu, 3 May 2007 07:51:35 +0200 Subject: [PATCH 18/28] Add --no-rebase option to git-svn dcommit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit git-svn dcommit exports commits to Subversion, then imports them back to git again, and last but not least rebases or resets HEAD to the last of the new commits. I guess this rebasing is convenient when using just git, but when the commits to be exported are managed by StGIT, it's really annoying. So add an option to disable this behavior. And document it, too! Signed-off-by: Karl Hasselström Acked-by: Eric Wong Signed-off-by: Junio C Hamano --- Documentation/git-svn.txt | 3 +++ git-svn.perl | 33 ++++++++++++++++++--------------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 820a2c308e..c0d7d9597b 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -119,6 +119,9 @@ and have no uncommitted changes. alternative to HEAD. This is advantageous over 'set-tree' (below) because it produces cleaner, more linear history. ++ +--no-rebase;; + After committing, do not rebase or reset. -- 'log':: diff --git a/git-svn.perl b/git-svn.perl index 6657e100fb..3c4f490b74 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -55,7 +55,7 @@ $sha1_short = qr/[a-f\d]{4,40}/; my ($_stdin, $_help, $_edit, $_message, $_file, $_template, $_shared, - $_version, $_fetch_all, + $_version, $_fetch_all, $_no_rebase, $_merge, $_strategy, $_dry_run, $_local, $_prefix, $_no_checkout, $_verbose); $Git::SVN::_follow_parent = 1; @@ -114,6 +114,7 @@ my %cmd = ( 'verbose|v' => \$_verbose, 'dry-run|n' => \$_dry_run, 'fetch-all|all' => \$_fetch_all, + 'no-rebase' => \$_no_rebase, %cmt_opts, %fc_opts } ], 'set-tree' => [ \&cmd_set_tree, "Set an SVN repository to a git tree-ish", @@ -413,21 +414,23 @@ sub cmd_dcommit { return; } $_fetch_all ? $gs->fetch_all : $gs->fetch; - # we always want to rebase against the current HEAD, not any - # head that was passed to us - my @diff = command('diff-tree', 'HEAD', $gs->refname, '--'); - my @finish; - if (@diff) { - @finish = rebase_cmd(); - print STDERR "W: HEAD and ", $gs->refname, " differ, ", - "using @finish:\n", "@diff"; - } else { - print "No changes between current HEAD and ", - $gs->refname, "\nResetting to the latest ", - $gs->refname, "\n"; - @finish = qw/reset --mixed/; + unless ($_no_rebase) { + # we always want to rebase against the current HEAD, not any + # head that was passed to us + my @diff = command('diff-tree', 'HEAD', $gs->refname, '--'); + my @finish; + if (@diff) { + @finish = rebase_cmd(); + print STDERR "W: HEAD and ", $gs->refname, " differ, ", + "using @finish:\n", "@diff"; + } else { + print "No changes between current HEAD and ", + $gs->refname, "\nResetting to the latest ", + $gs->refname, "\n"; + @finish = qw/reset --mixed/; + } + command_noisy(@finish, $gs->refname); } - command_noisy(@finish, $gs->refname); } sub cmd_find_rev { From 71f4b1834a8b4d1cb24ea326ca4a3fcc02796a5a Mon Sep 17 00:00:00 2001 From: Carl Worth Date: Fri, 4 May 2007 11:27:10 -0700 Subject: [PATCH 19/28] Mention version 1.5.1 in tutorial and user-manual Most other documentation will frequently be read from an installation of git so will naturally be associated with the installed version. But these two documents in particular are often read from web pages while users are still exploring git. It's important to mention version 1.5.1 since these documents provide example commands that won't work with previous versions of git. Signed-off-by: Junio C Hamano --- Documentation/tutorial.txt | 4 ++-- Documentation/user-manual.txt | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Documentation/tutorial.txt b/Documentation/tutorial.txt index e978562d6e..99efce4576 100644 --- a/Documentation/tutorial.txt +++ b/Documentation/tutorial.txt @@ -1,5 +1,5 @@ -A tutorial introduction to git -============================== +A tutorial introduction to git (for version 1.5.1 or newer) +=========================================================== This tutorial explains how to import a new project into git, make changes to it, and share changes with other developers. diff --git a/Documentation/user-manual.txt b/Documentation/user-manual.txt index 9c4c41df5a..dff438f768 100644 --- a/Documentation/user-manual.txt +++ b/Documentation/user-manual.txt @@ -1,5 +1,5 @@ -Git User's Manual -_________________ +Git User's Manual (for version 1.5.1 or newer) +______________________________________________ This manual is designed to be readable by someone with basic unix command-line skills, but no previous knowledge of git. From 3b559eab55693111e0922cd3dd41bfdba2e22989 Mon Sep 17 00:00:00 2001 From: Jakub Narebski Date: Sat, 5 May 2007 00:48:35 +0200 Subject: [PATCH 20/28] diff format documentation: describe raw combined diff format Add description of raw combined diff format to diff-formats.txt, as "diff format for merges" section, before "Generating patches..." section. Signed-off-by: Jakub Narebski Signed-off-by: Junio C Hamano --- Documentation/diff-format.txt | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/Documentation/diff-format.txt b/Documentation/diff-format.txt index 378e72f38f..e38a1f1405 100644 --- a/Documentation/diff-format.txt +++ b/Documentation/diff-format.txt @@ -59,6 +59,28 @@ When `-z` option is not used, TAB, LF, and backslash characters in pathnames are represented as `\t`, `\n`, and `\\`, respectively. +diff format for merges +---------------------- + +"git-diff-tree" and "git-diff-files" can take '-c' or '--cc' option +to generate diff output also for merge commits. The output differs +from the format described above in the following way: + +. there is a colon for each parent +. there are more "src" modes and "src" sha1 +. status is concatenated status characters for each parent +. no optional "score" number +. single path, only for "dst" + +Example: + +------------------------------------------------ +::100644 100644 100644 fabadb8... cc95eb0... 4866510... MM describe.c +------------------------------------------------ + +Note that 'combined diff' lists only files which were modified from +all parents. + Generating patches with -p -------------------------- From e330a406cd20cf45a6816929155181c37678bc47 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 5 May 2007 15:18:03 -0700 Subject: [PATCH 21/28] Fix --boundary output "git log --boundary" incorrectly honoured the option only when "left-right" was enabled. Signed-off-by: Linus Torvalds Signed-off-by: Junio C Hamano --- log-tree.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/log-tree.c b/log-tree.c index 8797aa14c4..dbd06490f9 100644 --- a/log-tree.c +++ b/log-tree.c @@ -218,10 +218,10 @@ void show_log(struct rev_info *opt, const char *sep) stdout); if (opt->commit_format != CMIT_FMT_ONELINE) fputs("commit ", stdout); - if (opt->left_right) { - if (commit->object.flags & BOUNDARY) - putchar('-'); - else if (commit->object.flags & SYMMETRIC_LEFT) + if (commit->object.flags & BOUNDARY) + putchar('-'); + else if (opt->left_right) { + if (commit->object.flags & SYMMETRIC_LEFT) putchar('<'); else putchar('>'); From dd166aa8e52dba39a3087b8012113af331d3110b Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 5 May 2007 09:13:26 -0700 Subject: [PATCH 22/28] blame: Notice a wholesale incorporation of an existing file. The -C option to blame tries to find a section of a preimage file by running diff against the lines whose origin is still unknown, and excluding the different parts. The code however did not cover the case where the tail part of the section matched, which we handle for the normal non-move/copy codepath. This breakage was most visible when preimage file matches in its entirety and failed to pass blame in such a case. Signed-off-by: Junio C Hamano --- builtin-blame.c | 52 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 12 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index 8919b028e6..f8843e6340 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -890,6 +890,39 @@ static void copy_split_if_better(struct scoreboard *sb, memcpy(best_so_far, this, sizeof(struct blame_entry [3])); } +/* + * We are looking at a part of the final image represented by + * ent (tlno and same are offset by ent->s_lno). + * tlno is where we are looking at in the final image. + * up to (but not including) same match preimage. + * plno is where we are looking at in the preimage. + * + * <-------------- final image ----------------------> + * <------ent------> + * ^tlno ^same + * <---------preimage-----> + * ^plno + * + * All line numbers are 0-based. + */ +static void handle_split(struct scoreboard *sb, + struct blame_entry *ent, + int tlno, int plno, int same, + struct origin *parent, + struct blame_entry *split) +{ + if (ent->num_lines <= tlno) + return; + if (tlno < same) { + struct blame_entry this[3]; + tlno += ent->s_lno; + same += ent->s_lno; + split_overlap(this, ent, tlno, plno, same, parent); + copy_split_if_better(sb, split, this); + decref_split(this); + } +} + /* * Find the lines from parent that are the same as ent so that * we can pass blames to it. file_p has the blob contents for @@ -922,26 +955,21 @@ static void find_copy_in_blob(struct scoreboard *sb, patch = compare_buffer(file_p, &file_o, 1); + /* + * file_o is a part of final image we are annotating. + * file_p partially may match that image. + */ memset(split, 0, sizeof(struct blame_entry [3])); plno = tlno = 0; for (i = 0; i < patch->num; i++) { struct chunk *chunk = &patch->chunks[i]; - /* tlno to chunk->same are the same as ent */ - if (ent->num_lines <= tlno) - break; - if (tlno < chunk->same) { - struct blame_entry this[3]; - split_overlap(this, ent, - tlno + ent->s_lno, plno, - chunk->same + ent->s_lno, - parent); - copy_split_if_better(sb, split, this); - decref_split(this); - } + handle_split(sb, ent, tlno, plno, chunk->same, parent, split); plno = chunk->p_next; tlno = chunk->t_next; } + /* remainder, if any, all match the preimage */ + handle_split(sb, ent, tlno, plno, ent->num_lines, parent, split); free_patch(patch); } From c63777c0d7687a1edff2c0da307ad8ac1d75c8f6 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 5 May 2007 21:18:57 -0700 Subject: [PATCH 23/28] blame: -C -C -C When you do this, existing "blame -C -C" would not find that the latter half of the file2 came from the existing file1: ... both file1 and file2 are tracked ... $ cat file1 >>file2 $ git add file1 file2 $ git commit This is because we avoid the expensive find-copies-harder code that makes unchanged file (in this case, file1) as a candidate for copy & paste source when annotating an existing file (file2). The third -C now allows it. However, this obviously makes the process very expensive. We've actually seen this patch before, but I dismissed it because it covers such a narrow (and arguably stupid) corner case. Signed-off-by: Junio C Hamano --- builtin-blame.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/builtin-blame.c b/builtin-blame.c index f8843e6340..65d029a773 100644 --- a/builtin-blame.c +++ b/builtin-blame.c @@ -55,6 +55,7 @@ static int num_commits; #define PICKAXE_BLAME_MOVE 01 #define PICKAXE_BLAME_COPY 02 #define PICKAXE_BLAME_COPY_HARDER 04 +#define PICKAXE_BLAME_COPY_HARDEST 010 /* * blame for a blame_entry with score lower than these thresholds @@ -1079,8 +1080,9 @@ static int find_copy_in_parent(struct scoreboard *sb, * and this code needs to be after diff_setup_done(), which * usually makes find-copies-harder imply copy detection. */ - if ((opt & PICKAXE_BLAME_COPY_HARDER) && - (!porigin || strcmp(target->path, porigin->path))) + if ((opt & PICKAXE_BLAME_COPY_HARDEST) + || ((opt & PICKAXE_BLAME_COPY_HARDER) + && (!porigin || strcmp(target->path, porigin->path)))) diff_opts.find_copies_harder = 1; if (is_null_sha1(target->commit->object.sha1)) @@ -2127,6 +2129,15 @@ int cmd_blame(int argc, const char **argv, const char *prefix) blame_move_score = parse_score(arg+2); } else if (!prefixcmp(arg, "-C")) { + /* + * -C enables copy from removed files; + * -C -C enables copy from existing files, but only + * when blaming a new file; + * -C -C -C enables copy from existing files for + * everybody + */ + if (opt & PICKAXE_BLAME_COPY_HARDER) + opt |= PICKAXE_BLAME_COPY_HARDEST; if (opt & PICKAXE_BLAME_COPY) opt |= PICKAXE_BLAME_COPY_HARDER; opt |= PICKAXE_BLAME_COPY | PICKAXE_BLAME_MOVE; From c2a063691e1dcec137ed1f0def406d3bf3567e71 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sat, 5 May 2007 22:36:19 -0700 Subject: [PATCH 24/28] Add test for blame corner cases. Signed-off-by: Junio C Hamano --- t/t8003-blame.sh | 132 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100755 t/t8003-blame.sh diff --git a/t/t8003-blame.sh b/t/t8003-blame.sh new file mode 100755 index 0000000000..db51b3a6bb --- /dev/null +++ b/t/t8003-blame.sh @@ -0,0 +1,132 @@ +#!/bin/sh + +test_description='git blame corner cases' +. ./test-lib.sh + +pick_fc='s/^[0-9a-f^]* *\([^ ]*\) *(\([^ ]*\) .*/\1-\2/' + +test_expect_success setup ' + + echo A A A A A >one && + echo B B B B B >two && + echo C C C C C >tres && + echo ABC >mouse && + git add one two tres mouse && + test_tick && + GIT_AUTHOR_NAME=Initial git commit -m Initial && + + cat one >uno && + mv two dos && + cat one >>tres && + echo DEF >>mouse + git add uno dos tres mouse && + test_tick && + GIT_AUTHOR_NAME=Second git commit -a -m Second && + + echo GHIJK >>mouse && + git add mouse && + test_tick && + GIT_AUTHOR_NAME=Third git commit -m Third && + + cat mouse >cow && + git add cow && + test_tick && + GIT_AUTHOR_NAME=Fourth git commit -m Fourth && + + { + echo ABC + echo DEF + echo XXXX + echo GHIJK + } >cow && + git add cow && + test_tick && + GIT_AUTHOR_NAME=Fifth git commit -m Fifth +' + +test_expect_success 'straight copy without -C' ' + + git blame uno | grep Second + +' + +test_expect_success 'straight move without -C' ' + + git blame dos | grep Initial + +' + +test_expect_success 'straight copy with -C' ' + + git blame -C1 uno | grep Second + +' + +test_expect_success 'straight move with -C' ' + + git blame -C1 dos | grep Initial + +' + +test_expect_success 'straight copy with -C -C' ' + + git blame -C -C1 uno | grep Initial + +' + +test_expect_success 'straight move with -C -C' ' + + git blame -C -C1 dos | grep Initial + +' + +test_expect_success 'append without -C' ' + + git blame -L2 tres | grep Second + +' + +test_expect_success 'append with -C' ' + + git blame -L2 -C1 tres | grep Second + +' + +test_expect_success 'append with -C -C' ' + + git blame -L2 -C -C1 tres | grep Second + +' + +test_expect_success 'append with -C -C -C' ' + + git blame -L2 -C -C -C1 tres | grep Initial + +' + +test_expect_success 'blame wholesale copy' ' + + git blame -f -C -C1 HEAD^ -- cow | sed -e "$pick_fc" >current && + { + echo mouse-Initial + echo mouse-Second + echo mouse-Third + } >expected && + diff -u expected current + +' + +test_expect_success 'blame wholesale copy and more' ' + + git blame -f -C -C1 HEAD -- cow | sed -e "$pick_fc" >current && + { + echo mouse-Initial + echo mouse-Second + echo cow-Fifth + echo mouse-Third + } >expected && + diff -u expected current + +' + +test_done From cf593cc41828c6fc0a2cec50ddac0713ea8a07ec Mon Sep 17 00:00:00 2001 From: James Bowes Date: Sat, 5 May 2007 14:23:12 -0400 Subject: [PATCH 25/28] Documentation: fix typo in git-remote.txt Signed-off-by: James Bowes Signed-off-by: Junio C Hamano --- Documentation/git-remote.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/git-remote.txt b/Documentation/git-remote.txt index a9fb6a9a5e..3dde7134a5 100644 --- a/Documentation/git-remote.txt +++ b/Documentation/git-remote.txt @@ -40,7 +40,7 @@ With `-t ` option, instead of the default glob refspec for the remote to track all branches under `$GIT_DIR/remotes//`, a refspec to track only `` is created. You can give more than one `-t ` to track -multiple branche without grabbing all branches. +multiple branches without grabbing all branches. + With `-m ` option, `$GIT_DIR/remotes//HEAD` is set up to point at remote's `` branch instead of whatever From e102d4353d7cfd69a597cd976eabdcb74641be69 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 4 May 2007 23:51:32 +0200 Subject: [PATCH 26/28] Small correction in reading of commit headers Check if a line of the header has enough characters to possibly contain the requested prefix. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- commit.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commit.c b/commit.c index eb911f44d7..7d78e786e9 100644 --- a/commit.c +++ b/commit.c @@ -640,7 +640,9 @@ static char *get_header(const struct commit *commit, const char *key) next = NULL; } else next = eol + 1; - if (!strncmp(line, key, key_len) && line[key_len] == ' ') { + if (eol - line > key_len && + !strncmp(line, key, key_len) && + line[key_len] == ' ') { int len = eol - line - key_len; char *ret = xmalloc(len); memcpy(ret, line + key_len + 1, len - 1); From cc0e6c5adc783bcb29954f3a0b7a6197bcc9b1b3 Mon Sep 17 00:00:00 2001 From: Alex Riesen Date: Fri, 4 May 2007 23:54:57 +0200 Subject: [PATCH 27/28] Handle return code of parse_commit in revision machinery This fixes a crash in broken repositories where random commits suddenly disappear. Signed-off-by: Alex Riesen Signed-off-by: Junio C Hamano --- revision.c | 73 +++++++++++++++++++++++++++++++++++++----------------- revision.h | 2 +- 2 files changed, 51 insertions(+), 24 deletions(-) diff --git a/revision.c b/revision.c index e60a26c6bb..0125d41136 100644 --- a/revision.c +++ b/revision.c @@ -318,7 +318,10 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) while ((parent = *pp) != NULL) { struct commit *p = parent->item; - parse_commit(p); + if (parse_commit(p) < 0) + die("cannot simplify commit %s (because of %s)", + sha1_to_hex(commit->object.sha1), + sha1_to_hex(p->object.sha1)); switch (rev_compare_tree(revs, p->tree, commit->tree)) { case REV_TREE_SAME: tree_same = 1; @@ -347,7 +350,10 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) * IOW, we pretend this parent is a * "root" commit. */ - parse_commit(p); + if (parse_commit(p) < 0) + die("cannot simplify commit %s (invalid %s)", + sha1_to_hex(commit->object.sha1), + sha1_to_hex(p->object.sha1)); p->parents = NULL; } /* fallthrough */ @@ -362,14 +368,14 @@ static void try_to_simplify_commit(struct rev_info *revs, struct commit *commit) commit->object.flags |= TREECHANGE; } -static void add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list) +static int add_parents_to_list(struct rev_info *revs, struct commit *commit, struct commit_list **list) { struct commit_list *parent = commit->parents; unsigned left_flag; int add, rest; if (commit->object.flags & ADDED) - return; + return 0; commit->object.flags |= ADDED; /* @@ -388,7 +394,8 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st while (parent) { struct commit *p = parent->item; parent = parent->next; - parse_commit(p); + if (parse_commit(p) < 0) + return -1; p->object.flags |= UNINTERESTING; if (p->parents) mark_parents_uninteresting(p); @@ -397,7 +404,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st p->object.flags |= SEEN; insert_by_date(p, list); } - return; + return 0; } /* @@ -409,7 +416,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st revs->prune_fn(revs, commit); if (revs->no_walk) - return; + return 0; left_flag = (commit->object.flags & SYMMETRIC_LEFT); @@ -418,7 +425,8 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st struct commit *p = parent->item; parent = parent->next; - parse_commit(p); + if (parse_commit(p) < 0) + return -1; p->object.flags |= left_flag; if (p->object.flags & SEEN) continue; @@ -426,6 +434,7 @@ static void add_parents_to_list(struct rev_info *revs, struct commit *commit, st if (add) insert_by_date(p, list); } + return 0; } static void cherry_pick_list(struct commit_list *list) @@ -508,7 +517,7 @@ static void cherry_pick_list(struct commit_list *list) free_patch_ids(&ids); } -static void limit_list(struct rev_info *revs) +static int limit_list(struct rev_info *revs) { struct commit_list *list = revs->commits; struct commit_list *newlist = NULL; @@ -524,7 +533,8 @@ static void limit_list(struct rev_info *revs) if (revs->max_age != -1 && (commit->date < revs->max_age)) obj->flags |= UNINTERESTING; - add_parents_to_list(revs, commit, &list); + if (add_parents_to_list(revs, commit, &list) < 0) + return -1; if (obj->flags & UNINTERESTING) { mark_parents_uninteresting(commit); if (everybody_uninteresting(list)) @@ -539,6 +549,7 @@ static void limit_list(struct rev_info *revs) cherry_pick_list(newlist); revs->commits = newlist; + return 0; } struct all_refs_cb { @@ -1227,7 +1238,7 @@ int setup_revisions(int argc, const char **argv, struct rev_info *revs, const ch return left; } -void prepare_revision_walk(struct rev_info *revs) +int prepare_revision_walk(struct rev_info *revs) { int nr = revs->pending.nr; struct object_array_entry *e, *list; @@ -1249,42 +1260,57 @@ void prepare_revision_walk(struct rev_info *revs) free(list); if (revs->no_walk) - return; + return 0; if (revs->limited) - limit_list(revs); + if (limit_list(revs) < 0) + return -1; if (revs->topo_order) sort_in_topological_order_fn(&revs->commits, revs->lifo, revs->topo_setter, revs->topo_getter); + return 0; } -static int rewrite_one(struct rev_info *revs, struct commit **pp) +enum rewrite_result { + rewrite_one_ok, + rewrite_one_noparents, + rewrite_one_error, +}; + +static enum rewrite_result rewrite_one(struct rev_info *revs, struct commit **pp) { for (;;) { struct commit *p = *pp; if (!revs->limited) - add_parents_to_list(revs, p, &revs->commits); + if (add_parents_to_list(revs, p, &revs->commits) < 0) + return rewrite_one_error; if (p->parents && p->parents->next) - return 0; + return rewrite_one_ok; if (p->object.flags & (TREECHANGE | UNINTERESTING)) - return 0; + return rewrite_one_ok; if (!p->parents) - return -1; + return rewrite_one_noparents; *pp = p->parents->item; } } -static void rewrite_parents(struct rev_info *revs, struct commit *commit) +static int rewrite_parents(struct rev_info *revs, struct commit *commit) { struct commit_list **pp = &commit->parents; while (*pp) { struct commit_list *parent = *pp; - if (rewrite_one(revs, &parent->item) < 0) { + switch (rewrite_one(revs, &parent->item)) { + case rewrite_one_ok: + break; + case rewrite_one_noparents: *pp = parent->next; continue; + case rewrite_one_error: + return -1; } pp = &parent->next; } + return 0; } static int commit_match(struct commit *commit, struct rev_info *opt) @@ -1320,7 +1346,8 @@ static struct commit *get_revision_1(struct rev_info *revs) if (revs->max_age != -1 && (commit->date < revs->max_age)) continue; - add_parents_to_list(revs, commit, &revs->commits); + if (add_parents_to_list(revs, commit, &revs->commits) < 0) + return NULL; } if (commit->object.flags & SHOWN) continue; @@ -1348,8 +1375,8 @@ static struct commit *get_revision_1(struct rev_info *revs) if (!commit->parents || !commit->parents->next) continue; } - if (revs->parents) - rewrite_parents(revs, commit); + if (revs->parents && rewrite_parents(revs, commit) < 0) + return NULL; } return commit; } while (revs->commits); diff --git a/revision.h b/revision.h index cdf94ad695..2845167746 100644 --- a/revision.h +++ b/revision.h @@ -113,7 +113,7 @@ extern void init_revisions(struct rev_info *revs, const char *prefix); extern int setup_revisions(int argc, const char **argv, struct rev_info *revs, const char *def); extern int handle_revision_arg(const char *arg, struct rev_info *revs,int flags,int cant_be_filename); -extern void prepare_revision_walk(struct rev_info *revs); +extern int prepare_revision_walk(struct rev_info *revs); extern struct commit *get_revision(struct rev_info *revs); extern void mark_parents_uninteresting(struct commit *commit); From 9159afbfce955db86373dab95b5f8e31fb763dae Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Sun, 6 May 2007 01:07:04 -0700 Subject: [PATCH 28/28] GIT v1.5.2-rc2 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.5.2.txt | 2 +- GIT-VERSION-GEN | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/RelNotes-1.5.2.txt b/Documentation/RelNotes-1.5.2.txt index 712ebb0b78..02b8ea0a68 100644 --- a/Documentation/RelNotes-1.5.2.txt +++ b/Documentation/RelNotes-1.5.2.txt @@ -171,6 +171,6 @@ this release, unless otherwise noted. -- exec >/var/tmp/1 -O=v1.5.2-rc0-106-g07c785d +O=v1.5.2-rc1-32-g125a5f1 echo O=`git describe refs/heads/master` git shortlog --no-merges $O..refs/heads/master ^refs/heads/maint diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 0a6ea68dec..f6adb91ed2 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.5.2-rc1.GIT +DEF_VER=v1.5.2-rc2.GIT LF=' '