From 8fdcf3125465f70c0cad5be5ab192d46e46307c7 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 29 Aug 2008 13:40:36 -0700 Subject: [PATCH 01/19] checkout: do not check out unmerged higher stages randomly During a conflicted merge when you have unmerged stages for a path F in the index, if you said: $ git checkout F we rewrote F as many times as we have stages for it, and the last one (typically "theirs") was left in the work tree, without resolving the conflict. This fixes it by noticing that a specified pathspec pattern matches an unmerged path, and by erroring out. Signed-off-by: Junio C Hamano --- builtin-checkout.c | 29 ++++++++++++++++++++++++++++- t/t7201-co.sh | 22 ++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/builtin-checkout.c b/builtin-checkout.c index 411cc513c6..8544010994 100644 --- a/builtin-checkout.c +++ b/builtin-checkout.c @@ -76,6 +76,15 @@ static int read_tree_some(struct tree *tree, const char **pathspec) return 0; } +static int skip_same_name(struct cache_entry *ce, int pos) +{ + while (++pos < active_nr && + !strcmp(active_cache[pos]->name, ce->name)) + ; /* skip */ + return pos; +} + + static int checkout_paths(struct tree *source_tree, const char **pathspec) { int pos; @@ -107,6 +116,20 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec) if (report_path_error(ps_matched, pathspec, 0)) return 1; + /* Any unmerged paths? */ + for (pos = 0; pos < active_nr; pos++) { + struct cache_entry *ce = active_cache[pos]; + if (pathspec_match(pathspec, NULL, ce->name, 0)) { + if (!ce_stage(ce)) + continue; + errs = 1; + error("path '%s' is unmerged", ce->name); + pos = skip_same_name(ce, pos) - 1; + } + } + if (errs) + return 1; + /* Now we are committed to check them out */ memset(&state, 0, sizeof(state)); state.force = 1; @@ -114,7 +137,11 @@ static int checkout_paths(struct tree *source_tree, const char **pathspec) for (pos = 0; pos < active_nr; pos++) { struct cache_entry *ce = active_cache[pos]; if (pathspec_match(pathspec, NULL, ce->name, 0)) { - errs |= checkout_entry(ce, &state, NULL); + if (!ce_stage(ce)) { + errs |= checkout_entry(ce, &state, NULL); + continue; + } + pos = skip_same_name(ce, pos) - 1; } } diff --git a/t/t7201-co.sh b/t/t7201-co.sh index 9ad5d635a2..83a366f1e7 100755 --- a/t/t7201-co.sh +++ b/t/t7201-co.sh @@ -337,4 +337,26 @@ test_expect_success \ test refs/heads/delete-me = "$(git symbolic-ref HEAD)" && test_must_fail git checkout --track -b track' +test_expect_success 'checkout an unmerged path should fail' ' + rm -f .git/index && + O=$(echo original | git hash-object -w --stdin) && + A=$(echo ourside | git hash-object -w --stdin) && + B=$(echo theirside | git hash-object -w --stdin) && + ( + echo "100644 $A 0 fild" && + echo "100644 $O 1 file" && + echo "100644 $A 2 file" && + echo "100644 $B 3 file" && + echo "100644 $A 0 filf" + ) | git update-index --index-info && + echo "none of the above" >sample && + cat sample >fild && + cat sample >file && + cat sample >filf && + test_must_fail git checkout fild file filf && + test_cmp sample fild && + test_cmp sample filf && + test_cmp sample file +' + test_done From 392809702016cde59d50a7b07e8c27f6d0ec3c3f Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 27 Aug 2008 19:48:01 -0700 Subject: [PATCH 02/19] diff: Help "less" hide ^M from the output When the tracked contents have CRLF line endings, colored diff output shows "^M" at the end of output lines, which is distracting, even though the pager we use by default ("less") knows to hide them. The problem is that "less" hides a carriage-return only at the end of the line, immediately before a line feed. The colored diff output does not take this into account, and emits four element sequence for each line: - force this color; - the line up to but not including the terminating line feed; - reset color - line feed. By including the carriage return at the end of the line in the second item, we are breaking the smart our pager has in order not to show "^M". This can be fixed by changing the sequence to: - force this color; - the line up to but not including the terminating end-of-line; - reset color - end-of-line. where end-of-line is either a single linefeed or a CRLF pair. When the output is not colored, "force this color" and "reset color" sequences are both empty, so we won't have this problem with or without this patch. Signed-off-by: Junio C Hamano --- combine-diff.c | 16 ++++++++++++++-- diff.c | 9 ++++++++- t/t4019-diff-wserror.sh | 12 ++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/combine-diff.c b/combine-diff.c index 4dfc330867..aa9d79ea0b 100644 --- a/combine-diff.c +++ b/combine-diff.c @@ -500,6 +500,18 @@ static int hunk_comment_line(const char *bol) return (isalpha(ch) || ch == '_' || ch == '$'); } +static void show_line_to_eol(const char *line, int len, const char *reset) +{ + int saw_cr_at_eol = 0; + if (len < 0) + len = strlen(line); + saw_cr_at_eol = (len && line[len-1] == '\r'); + + printf("%.*s%s%s\n", len - saw_cr_at_eol, line, + reset, + saw_cr_at_eol ? "\r" : ""); +} + static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, int use_color) { @@ -593,7 +605,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, else putchar(' '); } - printf("%s%s\n", ll->line, c_reset); + show_line_to_eol(ll->line, -1, c_reset); ll = ll->next; } if (cnt < lno) @@ -617,7 +629,7 @@ static void dump_sline(struct sline *sline, unsigned long cnt, int num_parent, putchar(' '); p_mask <<= 1; } - printf("%.*s%s\n", sl->len, sl->bol, c_reset); + show_line_to_eol(sl->bol, sl->len, c_reset); } } } diff --git a/diff.c b/diff.c index 7b4300a74a..6d56c69810 100644 --- a/diff.c +++ b/diff.c @@ -511,13 +511,20 @@ const char *diff_get_color(int diff_use_color, enum color_diff ix) static void emit_line(FILE *file, const char *set, const char *reset, const char *line, int len) { - int has_trailing_newline = (len > 0 && line[len-1] == '\n'); + int has_trailing_newline, has_trailing_carriage_return; + + has_trailing_newline = (len > 0 && line[len-1] == '\n'); if (has_trailing_newline) len--; + has_trailing_carriage_return = (len > 0 && line[len-1] == '\r'); + if (has_trailing_carriage_return) + len--; fputs(set, file); fwrite(line, len, 1, file); fputs(reset, file); + if (has_trailing_carriage_return) + fputc('\r', file); if (has_trailing_newline) fputc('\n', file); } diff --git a/t/t4019-diff-wserror.sh b/t/t4019-diff-wserror.sh index 7eae1f4500..84a1fe3115 100755 --- a/t/t4019-diff-wserror.sh +++ b/t/t4019-diff-wserror.sh @@ -178,4 +178,16 @@ test_expect_success 'trailing empty lines (2)' ' ' +test_expect_success 'do not color trailing cr in context' ' + git config --unset core.whitespace + rm -f .gitattributes && + echo AAAQ | tr Q "\015" >G && + git add G && + echo BBBQ | tr Q "\015" >>G + git diff --color G | tr "\015" Q >output && + grep "BBB.*${blue_grep}Q" output && + grep "AAA.*\[mQ" output + +' + test_done From 05207a28818623e417b69f337a9e8604d799d09d Mon Sep 17 00:00:00 2001 From: Heikki Orsila Date: Tue, 9 Sep 2008 13:28:30 +0300 Subject: [PATCH 03/19] Start conforming code to "git subcmd" style part 2 User notifications are presented as 'git cmd', and code comments are presented as '"cmd"' or 'git's cmd', rather than 'git-cmd'. Signed-off-by: Heikki Orsila Signed-off-by: Junio C Hamano --- builtin-checkout-index.c | 14 +++++++------- builtin-commit-tree.c | 2 +- builtin-fetch-pack.c | 2 +- builtin-fetch.c | 6 +++--- builtin-http-fetch.c | 4 ++-- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/builtin-checkout-index.c b/builtin-checkout-index.c index 90f8523eb5..55b7aafe06 100644 --- a/builtin-checkout-index.c +++ b/builtin-checkout-index.c @@ -5,26 +5,26 @@ * * Careful: order of argument flags does matter. For example, * - * git-checkout-index -a -f file.c + * git checkout-index -a -f file.c * * Will first check out all files listed in the cache (but not * overwrite any old ones), and then force-checkout "file.c" a * second time (ie that one _will_ overwrite any old contents * with the same filename). * - * Also, just doing "git-checkout-index" does nothing. You probably - * meant "git-checkout-index -a". And if you want to force it, you - * want "git-checkout-index -f -a". + * Also, just doing "git checkout-index" does nothing. You probably + * meant "git checkout-index -a". And if you want to force it, you + * want "git checkout-index -f -a". * * Intuitiveness is not the goal here. Repeatability is. The * reason for the "no arguments means no work" thing is that * from scripts you are supposed to be able to do things like * - * find . -name '*.h' -print0 | xargs -0 git-checkout-index -f -- + * find . -name '*.h' -print0 | xargs -0 git checkout-index -f -- * * or: * - * find . -name '*.h' -print0 | git-checkout-index -f -z --stdin + * find . -name '*.h' -print0 | git checkout-index -f -z --stdin * * which will force all existing *.h files to be replaced with * their cached copies. If an empty command line implied "all", @@ -107,7 +107,7 @@ static int checkout_file(const char *name, int prefix_length) } if (!state.quiet) { - fprintf(stderr, "git-checkout-index: %s ", name); + fprintf(stderr, "git checkout-index: %s ", name); if (!has_same_name) fprintf(stderr, "is not in the cache"); else if (checkout_stage) diff --git a/builtin-commit-tree.c b/builtin-commit-tree.c index 291c43cf70..9b84c48dce 100644 --- a/builtin-commit-tree.c +++ b/builtin-commit-tree.c @@ -24,7 +24,7 @@ static void check_valid(unsigned char *sha1, enum object_type expect) typename(expect)); } -static const char commit_tree_usage[] = "git-commit-tree [-p ]* < changelog"; +static const char commit_tree_usage[] = "git commit-tree [-p ]* < changelog"; static void new_parent(struct commit *parent, struct commit_list **parents_p) { diff --git a/builtin-fetch-pack.c b/builtin-fetch-pack.c index 6b37281a95..85509f5ee5 100644 --- a/builtin-fetch-pack.c +++ b/builtin-fetch-pack.c @@ -750,7 +750,7 @@ int cmd_fetch_pack(int argc, const char **argv, const char *prefix) if (!ret && nr_heads) { /* If the heads to pull were given, we should have * consumed all of them by matching the remote. - * Otherwise, 'git-fetch remote no-such-ref' would + * Otherwise, 'git fetch remote no-such-ref' would * silently succeed without issuing an error. */ for (i = 0; i < nr_heads; i++) diff --git a/builtin-fetch.c b/builtin-fetch.c index 7eec4a0e43..ee93d3a93d 100644 --- a/builtin-fetch.c +++ b/builtin-fetch.c @@ -86,10 +86,10 @@ static void add_merge_config(struct ref **head, /* * Not fetched to a tracking branch? We need to fetch * it anyway to allow this branch's "branch.$name.merge" - * to be honored by git-pull, but we do not have to + * to be honored by 'git pull', but we do not have to * fail if branch.$name.merge is misconfigured to point * at a nonexisting branch. If we were indeed called by - * git-pull, it will notice the misconfiguration because + * 'git pull', it will notice the misconfiguration because * there is no entry in the resulting FETCH_HEAD marked * for merging. */ @@ -396,7 +396,7 @@ static int store_updated_refs(const char *url, const char *remote_name, * The refs we are going to fetch are in to_fetch (nr_heads in * total). If running * - * $ git-rev-list --objects to_fetch[0] to_fetch[1] ... --not --all + * $ git rev-list --objects to_fetch[0] to_fetch[1] ... --not --all * * does not error out, that means everything reachable from the * refs we are going to fetch exists and is connected to some of diff --git a/builtin-http-fetch.c b/builtin-http-fetch.c index 3a062487a7..03f34d767d 100644 --- a/builtin-http-fetch.c +++ b/builtin-http-fetch.c @@ -42,7 +42,7 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix) arg++; } if (argc < arg + 2 - commits_on_stdin) { - usage("git-http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); + usage("git http-fetch [-c] [-t] [-a] [-v] [--recover] [-w ref] [--stdin] commit-id url"); return 1; } if (commits_on_stdin) { @@ -75,7 +75,7 @@ int cmd_http_fetch(int argc, const char **argv, const char *prefix) fprintf(stderr, "Some loose object were found to be corrupt, but they might be just\n" "a false '404 Not Found' error message sent with incorrect HTTP\n" -"status code. Suggest running git-fsck.\n"); +"status code. Suggest running 'git fsck'.\n"); } walker_free(walker); From 1e368681bd8c35202b91f8998e07d8bbb3de6c7c Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Wed, 10 Sep 2008 19:32:44 +0200 Subject: [PATCH 04/19] t7501: always use test_cmp instead of diff This should make the output more readable (by default using diff -u) when some tests fail. Also changed the diff order from "current expected" to "expected current". Signed-off-by: Miklos Vajna Signed-off-by: Junio C Hamano --- t/t7501-commit.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/t/t7501-commit.sh b/t/t7501-commit.sh index 469bff8873..63bfc6d8b3 100755 --- a/t/t7501-commit.sh +++ b/t/t7501-commit.sh @@ -141,7 +141,7 @@ EOF test_expect_success \ 'validate git rev-list output.' \ - 'diff current expected' + 'test_cmp expected current' test_expect_success 'partial commit that involves removal (1)' ' @@ -151,7 +151,7 @@ test_expect_success 'partial commit that involves removal (1)' ' git commit -m "Partial: add elif" elif && git diff-tree --name-status HEAD^ HEAD >current && echo "A elif" >expected && - diff expected current + test_cmp expected current ' @@ -160,7 +160,7 @@ test_expect_success 'partial commit that involves removal (2)' ' git commit -m "Partial: remove file" file && git diff-tree --name-status HEAD^ HEAD >current && echo "D file" >expected && - diff expected current + test_cmp expected current ' @@ -171,7 +171,7 @@ test_expect_success 'partial commit that involves removal (3)' ' git commit -m "Partial: modify elif" elif && git diff-tree --name-status HEAD^ HEAD >current && echo "M elif" >expected && - diff expected current + test_cmp expected current ' @@ -187,7 +187,7 @@ test_expect_success 'amend commit to fix author' ' expected && git commit --amend --author="$author" && git cat-file -p HEAD > current && - diff expected current + test_cmp expected current ' @@ -256,7 +256,7 @@ test_expect_success 'amend commit to fix author' ' expected && git commit --amend --author="$author" && git cat-file -p HEAD > current && - diff expected current + test_cmp expected current ' From 836ff95df6de9924cf8cf23515e3779a67a6bdec Mon Sep 17 00:00:00 2001 From: Marcus Griep Date: Mon, 8 Sep 2008 12:53:01 -0400 Subject: [PATCH 05/19] Git.pm: Use File::Temp->tempfile instead of ->new Perl 5.8.0 ships with File::Temp 0.13, which does not have the new() interface introduced in 0.14, as pointed out by Tom G. Christensen. This modifies Git.pm to use the more established tempfile() interface and updates 'git svn' to match. Signed-off-by: Marcus Griep Acked-by: Eric Wong Tested-by: Tom G. Christensen Signed-off-by: Junio C Hamano --- git-svn.perl | 4 ++-- perl/Git.pm | 42 ++++++++++++++++++++++++++++++------------ 2 files changed, 32 insertions(+), 14 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index 7a1d26db8b..95c6c85bbd 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3284,7 +3284,7 @@ sub close_file { my $out = syswrite($tmp_fh, $str, $res); defined($out) && $out == $res or croak("write ", - $tmp_fh->filename, + Git::temp_path($tmp_fh), ": $!\n"); } defined $res or croak $!; @@ -3295,7 +3295,7 @@ sub close_file { } $hash = $::_repository->hash_and_insert_object( - $fh->filename); + Git::temp_path($fh)); $hash =~ /^[a-f\d]{40}$/ or die "not a sha1: $hash\n"; Git::temp_release($fb->{base}, 1); diff --git a/perl/Git.pm b/perl/Git.pm index 102e6a4ce3..6aab712e6a 100644 --- a/perl/Git.pm +++ b/perl/Git.pm @@ -58,7 +58,7 @@ require Exporter; command_bidi_pipe command_close_bidi_pipe version exec_path hash_object git_cmd_try remote_refs - temp_acquire temp_release temp_reset); + temp_acquire temp_release temp_reset temp_path); =head1 DESCRIPTION @@ -937,7 +937,7 @@ sub _close_cat_blob { { # %TEMP_* Lexical Context -my (%TEMP_LOCKS, %TEMP_FILES); +my (%TEMP_FILEMAP, %TEMP_FILES); =item temp_acquire ( NAME ) @@ -965,7 +965,7 @@ sub temp_acquire { my $temp_fd = _temp_cache($name); - $TEMP_LOCKS{$temp_fd} = 1; + $TEMP_FILES{$temp_fd}{locked} = 1; $temp_fd; } @@ -991,16 +991,16 @@ the same string. sub temp_release { my ($self, $temp_fd, $trunc) = _maybe_self(@_); - if (ref($temp_fd) ne 'File::Temp') { + if (exists $TEMP_FILEMAP{$temp_fd}) { $temp_fd = $TEMP_FILES{$temp_fd}; } - unless ($TEMP_LOCKS{$temp_fd}) { + unless ($TEMP_FILES{$temp_fd}{locked}) { carp "Attempt to release temp file '", $temp_fd, "' that has not been locked"; } temp_reset($temp_fd) if $trunc and $temp_fd->opened; - $TEMP_LOCKS{$temp_fd} = 0; + $TEMP_FILES{$temp_fd}{locked} = 0; undef; } @@ -1009,9 +1009,9 @@ sub _temp_cache { _verify_require(); - my $temp_fd = \$TEMP_FILES{$name}; + my $temp_fd = \$TEMP_FILEMAP{$name}; if (defined $$temp_fd and $$temp_fd->opened) { - if ($TEMP_LOCKS{$$temp_fd}) { + if ($TEMP_FILES{$$temp_fd}{locked}) { throw Error::Simple("Temp file with moniker '", $name, "' already in use"); } @@ -1021,12 +1021,13 @@ sub _temp_cache { carp "Temp file '", $name, "' was closed. Opening replacement."; } - $$temp_fd = File::Temp->new( - TEMPLATE => 'Git_XXXXXX', - DIR => File::Spec->tmpdir + my $fname; + ($$temp_fd, $fname) = File::Temp->tempfile( + 'Git_XXXXXX', UNLINK => 1 ) or throw Error::Simple("couldn't open new temp file"); $$temp_fd->autoflush; binmode $$temp_fd; + $TEMP_FILES{$$temp_fd}{fname} = $fname; } $$temp_fd; } @@ -1053,8 +1054,25 @@ sub temp_reset { or throw Error::Simple("expected file position to be reset"); } +=item temp_path ( NAME ) + +=item temp_path ( FILEHANDLE ) + +Returns the filename associated with the given tempfile. + +=cut + +sub temp_path { + my ($self, $temp_fd) = _maybe_self(@_); + + if (exists $TEMP_FILEMAP{$temp_fd}) { + $temp_fd = $TEMP_FILEMAP{$temp_fd}; + } + $TEMP_FILES{$temp_fd}{fname}; +} + sub END { - unlink values %TEMP_FILES if %TEMP_FILES; + unlink values %TEMP_FILEMAP if %TEMP_FILEMAP; } } # %TEMP_* Lexical Context From 971e628384fea14e9c0bf96e1c69b97df6ec540e Mon Sep 17 00:00:00 2001 From: Marcus Griep Date: Wed, 10 Sep 2008 11:09:46 -0400 Subject: [PATCH 06/19] git-svn: Fixes my() parameter list syntax error in pre-5.8 Perl Signed-off-by: Marcus Griep Signed-off-by: Junio C Hamano --- git-svn.perl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/git-svn.perl b/git-svn.perl index 95c6c85bbd..237895c236 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -4383,7 +4383,7 @@ sub config_pager { sub run_pager { return unless -t *STDOUT && defined $pager; - pipe my $rfd, my $wfd or return; + pipe my ($rfd, $wfd) or return; defined(my $pid = fork) or ::fatal "Can't fork: $!"; if (!$pid) { open STDOUT, '>&', $wfd or From 3632cfc2487afc41c7c9e939a9d357daca3e5d67 Mon Sep 17 00:00:00 2001 From: Arjen Laarhoven Date: Sun, 7 Sep 2008 20:45:37 +0200 Subject: [PATCH 07/19] Use compatibility regex library for OSX/Darwin The standard libc regex library on OSX does not support alternation in POSIX Basic Regular Expression mode. This breaks the diff.funcname functionality on OSX. To fix this, we use the GNU regex library which is already present in the compat/ diretory for the MinGW port. However, simply adding compat/ to the COMPAT_CFLAGS variable causes a conflict between the system fnmatch.h and the one present in compat/. To remedy this, move the regex and fnmatch functionality to their own subdirectories in compat/ so they can be included seperately. Signed-off-by: Arjen Laarhoven Tested-by: Mike Ralphson (AIX) Tested-by: Johannes Sixt (MinGW) Signed-off-by: Junio C Hamano --- Makefile | 6 ++++-- compat/{ => fnmatch}/fnmatch.c | 0 compat/{ => fnmatch}/fnmatch.h | 0 compat/{ => regex}/regex.c | 0 compat/{ => regex}/regex.h | 0 t/t4018-diff-funcname.sh | 6 ++++++ 6 files changed, 10 insertions(+), 2 deletions(-) rename compat/{ => fnmatch}/fnmatch.c (100%) rename compat/{ => fnmatch}/fnmatch.h (100%) rename compat/{ => regex}/regex.c (100%) rename compat/{ => regex}/regex.h (100%) diff --git a/Makefile b/Makefile index 672ea74233..a8b3f9e3c5 100644 --- a/Makefile +++ b/Makefile @@ -626,6 +626,8 @@ ifeq ($(uname_S),Darwin) endif NO_STRLCPY = YesPlease NO_MEMMEM = YesPlease + COMPAT_CFLAGS += -Icompat/regex + COMPAT_OBJS += compat/regex/regex.o endif ifeq ($(uname_S),SunOS) NEEDS_SOCKET = YesPlease @@ -750,10 +752,10 @@ ifneq (,$(findstring MINGW,$(uname_S))) NO_SVN_TESTS = YesPlease NO_PERL_MAKEMAKER = YesPlease NO_POSIX_ONLY_PROGRAMS = YesPlease - COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat + COMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/regex -Icompat/fnmatch COMPAT_CFLAGS += -DSNPRINTF_SIZE_CORR=1 COMPAT_CFLAGS += -DSTRIP_EXTENSION=\".exe\" - COMPAT_OBJS += compat/mingw.o compat/fnmatch.o compat/regex.o compat/winansi.o + COMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/regex/regex.o compat/winansi.o EXTLIBS += -lws2_32 X = .exe gitexecdir = ../libexec/git-core diff --git a/compat/fnmatch.c b/compat/fnmatch/fnmatch.c similarity index 100% rename from compat/fnmatch.c rename to compat/fnmatch/fnmatch.c diff --git a/compat/fnmatch.h b/compat/fnmatch/fnmatch.h similarity index 100% rename from compat/fnmatch.h rename to compat/fnmatch/fnmatch.h diff --git a/compat/regex.c b/compat/regex/regex.c similarity index 100% rename from compat/regex.c rename to compat/regex/regex.c diff --git a/compat/regex.h b/compat/regex/regex.h similarity index 100% rename from compat/regex.h rename to compat/regex/regex.h diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 833d6cbcfc..18bcd9713d 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -57,4 +57,10 @@ test_expect_success 'last regexp must not be negated' ' test_must_fail git diff --no-index Beer.java Beer-correct.java ' +test_expect_success 'alternation in pattern' ' + git config diff.java.funcname "^[ ]*\\(\\(public\\|static\\).*\\)$" + git diff --no-index Beer.java Beer-correct.java | + grep "^@@.*@@ public static void main(" +' + test_done From 873358dd2ac3bf2cea9a370d8586378a27a092f2 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Wed, 10 Sep 2008 12:45:02 -0700 Subject: [PATCH 08/19] Update draft release notes for 1.6.0.2 Signed-off-by: Junio C Hamano --- Documentation/RelNotes-1.6.0.2.txt | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Documentation/RelNotes-1.6.0.2.txt b/Documentation/RelNotes-1.6.0.2.txt index 6c5446bc07..7a9646fc4f 100644 --- a/Documentation/RelNotes-1.6.0.2.txt +++ b/Documentation/RelNotes-1.6.0.2.txt @@ -17,6 +17,10 @@ Fixes since v1.6.0.1 * Many commands did not use the correct working tree location when used with GIT_WORK_TREE environment settings. +* Some systems needs to use compatibility fnmach and regex libraries + independent from each other; the compat/ area has been reorganized to + allow this. + * "git apply --unidiff-zero" incorrectly applied a -U0 patch that inserts a new line before the second line. @@ -24,9 +28,15 @@ Fixes since v1.6.0.1 * "git blame -c" did not exactly work like "git annotate" when range boundaries are involved. +* "git checkout file" when file is still unmerged checked out contents from + a random high order stage, which was confusing. + * "git clone $there $here/" with extra trailing slashes after explicit local directory name $here did not work as expected. +* "git diff" on tracked contents with CRLF line endings did not drive "less" + intelligently when showing added or removed lines. + * "git diff --dirstat -M" did not add changes in subdirectories up correctly for renamed paths. @@ -42,18 +52,29 @@ Fixes since v1.6.0.1 * "git gui" translation updates and i18n fixes. +* "git index-pack" is more careful against disk corruption while completing + a thin pack. + * "git log -i --grep=pattern" did not ignore case; neither "git log -E --grep=pattern" triggered extended regexp. * "git log --pretty="%ad" --date=short" did not use short format when showing the timestamp. +* "git log --author=author" match incorrectly matched with the + timestamp part of "author " line in commit objects. + +* "git log -F --author=author" did not work at all. + * Build procedure for "git shell" that used stub versions of some functions and globals was not understood by linkers on some platforms. * "git stash" was fooled by a stat-dirty but otherwise unmodified paths and refused to work until the user refreshed the index. +* "git svn" was broken on Perl before 5.8 with recent fixes to reduce + use of temporary files. + * "git verify-pack -v" did not work correctly when given more than one packfile. @@ -61,7 +82,6 @@ Also contains many documentation updates. -- exec >/var/tmp/1 -O=v1.6.0.1-61-g1eff26c +O=v1.6.0.1-78-g3632cfc echo O=$(git describe maint) git shortlog --no-merges $O..maint - From 9c101b3e6ff23378447bacd537a3dea57b1eed35 Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Thu, 11 Sep 2008 10:14:44 +0200 Subject: [PATCH 09/19] Use compatibility regex library also on AIX This augments 3632cfc24 (Use compatibility regex library on Darwin, 2008-09-07), which already carries a "Tested-by" statement for AIX, but that test was actually done with this patch included. Signed-off-by: Johannes Sixt Tested-by: Mike Ralphson Signed-off-by: Junio C Hamano --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index a8b3f9e3c5..3a9de88123 100644 --- a/Makefile +++ b/Makefile @@ -702,6 +702,8 @@ ifeq ($(uname_S),AIX) INTERNAL_QSORT = UnfortunatelyYes NEEDS_LIBICONV=YesPlease BASIC_CFLAGS += -D_LARGE_FILES + COMPAT_CFLAGS += -Icompat/regex + COMPAT_OBJS += compat/regex/regex.o endif ifeq ($(uname_S),GNU) # GNU/Hurd From 06e75d9ac7d03bb41bb9cd8e236d9dba635d44fd Mon Sep 17 00:00:00 2001 From: Jeff King Date: Thu, 11 Sep 2008 08:12:16 -0400 Subject: [PATCH 10/19] Use compatibility regex library also on FreeBSD Commit 3632cfc24 makes the same change for Darwin; however, the problem also exists on FreeBSD. Signed-off-by: Jeff King Signed-off-by: Junio C Hamano --- Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Makefile b/Makefile index 3a9de88123..8d81095765 100644 --- a/Makefile +++ b/Makefile @@ -677,6 +677,8 @@ ifeq ($(uname_S),FreeBSD) BASIC_CFLAGS += -I/usr/local/include BASIC_LDFLAGS += -L/usr/local/lib DIR_HAS_BSD_GROUP_SEMANTICS = YesPlease + COMPAT_CFLAGS += -Icompat/regex + COMPAT_OBJS += compat/regex/regex.o endif ifeq ($(uname_S),OpenBSD) NO_STRCASESTR = YesPlease From b66e00f12a4e0eef7c9f994db5386e066d726778 Mon Sep 17 00:00:00 2001 From: Ralf Wildenhues Date: Fri, 12 Sep 2008 21:10:26 +0200 Subject: [PATCH 11/19] Fix some manual typos. Signed-off-by: Ralf Wildenhues Signed-off-by: Junio C Hamano --- Documentation/git-web--browse.txt | 2 +- Documentation/gitattributes.txt | 2 +- Documentation/merge-config.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Documentation/git-web--browse.txt b/Documentation/git-web--browse.txt index 36afad8d4e..7f7a45b2ea 100644 --- a/Documentation/git-web--browse.txt +++ b/Documentation/git-web--browse.txt @@ -77,7 +77,7 @@ the URLs passed as arguments. Note about konqueror -------------------- -When 'konqueror' is specified by the a command line option or a +When 'konqueror' is specified by a command line option or a configuration variable, we launch 'kfmclient' to try to open the HTML man page on an already opened konqueror in a new tab if possible. diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 49a167f241..94e6752aa2 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -311,7 +311,7 @@ patterns are available: - `bibtex` suitable for files with BibTeX coded references. -- `java` suitable for source code in the Java lanugage. +- `java` suitable for source code in the Java language. - `pascal` suitable for source code in the Pascal/Delphi language. diff --git a/Documentation/merge-config.txt b/Documentation/merge-config.txt index 00277e0613..c735788b0f 100644 --- a/Documentation/merge-config.txt +++ b/Documentation/merge-config.txt @@ -1,5 +1,5 @@ merge.stat:: - Whether to print the diffstat between ORIG_HEAD and merge result + Whether to print the diffstat between ORIG_HEAD and the merge result at the end of the merge. True by default. merge.log:: From 97a7a82f199f165f85fe39a3c318b18c621e6335 Mon Sep 17 00:00:00 2001 From: Junio C Hamano Date: Fri, 12 Sep 2008 16:18:47 -0700 Subject: [PATCH 12/19] GIT 1.6.0.2 Signed-off-by: Junio C Hamano --- Documentation/git.txt | 4 +++- GIT-VERSION-GEN | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Documentation/git.txt b/Documentation/git.txt index 363a785452..df420aeb33 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,11 @@ unreleased) version of git, that is available from 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v1.6.0/git.html[documentation for release 1.6.0] +* link:v1.6.0.2/git.html[documentation for release 1.6.0.2] * release notes for + link:RelNotes-1.6.0.2.txt[1.6.0.2], + link:RelNotes-1.6.0.1.txt[1.6.0.1], link:RelNotes-1.6.0.txt[1.6.0]. * link:v1.5.6.5/git.html[documentation for release 1.5.6.5] diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 156dc13733..6c7465c758 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v1.6.0.GIT +DEF_VER=v1.6.0.2.GIT LF=' ' From 8409bb3708e1dd7c035617795c49e4ca7e17c56a Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Mon, 15 Sep 2008 11:23:24 -0500 Subject: [PATCH 13/19] t9700/test.pl: avoid bareword 'STDERR' in 3-argument open() Some versions of perl complain when 'STDERR' is used as the third argument in the 3-argument form of open(). Convert to the 2-argument form which is described for duping STDERR in my second edition camel book. Signed-off-by: Brandon Casey Tested-by: Tom G. Christensen on RHEL 3, Perl 5.8.0 Signed-off-by: Junio C Hamano --- t/t9700/test.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/t9700/test.pl b/t/t9700/test.pl index 4d2312548a..b47c71989a 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -38,7 +38,7 @@ is($r->get_color("color.test.slot1", "red"), $ansi_green, "get_color"); # Failure cases for config: # Save and restore STDERR; we will probably extract this into a # "dies_ok" method and possibly move the STDERR handling to Git.pm. -open our $tmpstderr, ">&", STDERR or die "cannot save STDERR"; close STDERR; +open our $tmpstderr, ">&STDERR" or die "cannot save STDERR"; close STDERR; eval { $r->config("test.dupstring") }; ok($@, "config: duplicate entry in scalar context fails"); eval { $r->config_bool("test.boolother") }; From bf55778855c2c95fdc4919a4d42ee68d348b75ef Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Mon, 15 Sep 2008 11:25:22 -0500 Subject: [PATCH 14/19] t9700/test.pl: remove File::Temp requirement The object oriented version of File::Temp is a rather new incarnation it seems. The File::Temp man page for v5.8.0 says "(NOT YET IMPLEMENTED)" in the 'Objects' section. Instead of creating a file with a unique name in the system TMPDIR, we can create our own temporary file with a static name and use that instead. Signed-off-by: Brandon Casey Tested-by: Tom G. Christensen on RHEL 3, Perl 5.8.0 Signed-off-by: Junio C Hamano --- t/t9700/test.pl | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/t/t9700/test.pl b/t/t9700/test.pl index b47c71989a..504f95a47d 100755 --- a/t/t9700/test.pl +++ b/t/t9700/test.pl @@ -9,7 +9,6 @@ use Test::More qw(no_plan); use Cwd; use File::Basename; -use File::Temp; BEGIN { use_ok('Git') } @@ -69,21 +68,25 @@ is($r->ident_person("Name", "email", "123 +0000"), "Name ", # objects and hashes ok(our $file1hash = $r->command_oneline('rev-parse', "HEAD:file1"), "(get file hash)"); -our $tmpfile = File::Temp->new; -is($r->cat_blob($file1hash, $tmpfile), 15, "cat_blob: size"); +my $tmpfile = "file.tmp"; +open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!"; +is($r->cat_blob($file1hash, \*TEMPFILE), 15, "cat_blob: size"); our $blobcontents; -{ local $/; seek $tmpfile, 0, 0; $blobcontents = <$tmpfile>; } +{ local $/; seek TEMPFILE, 0, 0; $blobcontents = ; } is($blobcontents, "changed file 1\n", "cat_blob: data"); -seek $tmpfile, 0, 0; +close TEMPFILE or die "Failed writing to $tmpfile: $!"; is(Git::hash_object("blob", $tmpfile), $file1hash, "hash_object: roundtrip"); -$tmpfile = File::Temp->new(); -print $tmpfile my $test_text = "test blob, to be inserted\n"; +open TEMPFILE, ">$tmpfile" or die "Can't open $tmpfile: $!"; +print TEMPFILE my $test_text = "test blob, to be inserted\n"; +close TEMPFILE or die "Failed writing to $tmpfile: $!"; like(our $newhash = $r->hash_and_insert_object($tmpfile), qr/[0-9a-fA-F]{40}/, "hash_and_insert_object: returns hash"); -$tmpfile = File::Temp->new; -is($r->cat_blob($newhash, $tmpfile), length $test_text, "cat_blob: roundtrip size"); -{ local $/; seek $tmpfile, 0, 0; $blobcontents = <$tmpfile>; } +open TEMPFILE, "+>$tmpfile" or die "Can't open $tmpfile: $!"; +is($r->cat_blob($newhash, \*TEMPFILE), length $test_text, "cat_blob: roundtrip size"); +{ local $/; seek TEMPFILE, 0, 0; $blobcontents = ; } is($blobcontents, $test_text, "cat_blob: roundtrip data"); +close TEMPFILE; +unlink $tmpfile; # paths is($r->repo_path, "./.git", "repo_path"); From f18d244a6356947cf0fb753b43c0d6ac4c7b5637 Mon Sep 17 00:00:00 2001 From: Heikki Orsila Date: Sat, 13 Sep 2008 20:18:36 +0300 Subject: [PATCH 15/19] Start conforming code to "git subcmd" style part 3 User notifications are presented as 'git cmd', and code comments are presented as '"cmd"' or 'git's cmd', rather than 'git-cmd'. Signed-off-by: Heikki Orsila Signed-off-by: Junio C Hamano --- builtin-init-db.c | 2 +- builtin-pack-objects.c | 4 ++-- builtin-read-tree.c | 2 +- builtin-rev-list.c | 2 +- builtin-rm.c | 2 +- builtin-send-pack.c | 2 +- builtin-tar-tree.c | 14 +++++++------- builtin-unpack-objects.c | 2 +- builtin-update-index.c | 8 ++++---- 9 files changed, 19 insertions(+), 19 deletions(-) diff --git a/builtin-init-db.c b/builtin-init-db.c index baf0d09ac4..8140c1299a 100644 --- a/builtin-init-db.c +++ b/builtin-init-db.c @@ -37,7 +37,7 @@ static void copy_templates_1(char *path, int baselen, /* Note: if ".git/hooks" file exists in the repository being * re-initialized, /etc/core-git/templates/hooks/update would - * cause git-init to fail here. I think this is sane but + * cause "git init" to fail here. I think this is sane but * it means that the set of templates we ship by default, along * with the way the namespace under .git/ is organized, should * be really carefully chosen. diff --git a/builtin-pack-objects.c b/builtin-pack-objects.c index ba2cf00f5e..217fd49da9 100644 --- a/builtin-pack-objects.c +++ b/builtin-pack-objects.c @@ -23,7 +23,7 @@ #endif static const char pack_usage[] = "\ -git-pack-objects [{ -q | --progress | --all-progress }] \n\ +git pack-objects [{ -q | --progress | --all-progress }] \n\ [--max-pack-size=N] [--local] [--incremental] \n\ [--window=N] [--window-memory=N] [--depth=N] \n\ [--no-reuse-delta] [--no-reuse-object] [--delta-base-offset] \n\ @@ -1872,7 +1872,7 @@ static void mark_in_pack_object(struct object *object, struct packed_git *p, str /* * Compare the objects in the offset order, in order to emulate the - * "git-rev-list --objects" output that produced the pack originally. + * "git rev-list --objects" output that produced the pack originally. */ static int ofscmp(const void *a_, const void *b_) { diff --git a/builtin-read-tree.c b/builtin-read-tree.c index dddc3044b8..ac219ac2db 100644 --- a/builtin-read-tree.c +++ b/builtin-read-tree.c @@ -64,7 +64,7 @@ static void prime_cache_tree(void) } -static const char read_tree_usage[] = "git-read-tree ( | [[-m [--trivial] [--aggressive] | --reset | --prefix=] [-u | -i]] [--exclude-per-directory=] [--index-output=] [ []])"; +static const char read_tree_usage[] = "git read-tree ( | [[-m [--trivial] [--aggressive] | --reset | --prefix=] [-u | -i]] [--exclude-per-directory=] [--index-output=] [ []])"; static struct lock_file lock_file; diff --git a/builtin-rev-list.c b/builtin-rev-list.c index c023003b2b..facaff288d 100644 --- a/builtin-rev-list.c +++ b/builtin-rev-list.c @@ -178,7 +178,7 @@ static void finish_object(struct object_array_entry *p) static void show_object(struct object_array_entry *p) { /* An object with name "foo\n0000000..." can be used to - * confuse downstream git-pack-objects very badly. + * confuse downstream "git pack-objects" very badly. */ const char *ep = strchr(p->name, '\n'); diff --git a/builtin-rm.c b/builtin-rm.c index 6bd82111d2..fdac34f242 100644 --- a/builtin-rm.c +++ b/builtin-rm.c @@ -104,7 +104,7 @@ static int check_local_mod(unsigned char *head, int index_only) "from both the file and the HEAD\n" "(use -f to force removal)", name); else if (!index_only) { - /* It's not dangerous to git-rm --cached a + /* It's not dangerous to "git rm --cached" a * file if the index matches the file or the * HEAD, since it means the deleted content is * still available somewhere. diff --git a/builtin-send-pack.c b/builtin-send-pack.c index 7588d22885..2af9f29341 100644 --- a/builtin-send-pack.c +++ b/builtin-send-pack.c @@ -43,7 +43,7 @@ static int pack_objects(int fd, struct ref *refs) po.out = fd; po.git_cmd = 1; if (start_command(&po)) - die("git-pack-objects failed (%s)", strerror(errno)); + die("git pack-objects failed (%s)", strerror(errno)); /* * We feed the pack-objects we just spawned with revision diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index cb7007e25f..419a69b507 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -9,19 +9,19 @@ static const char tar_tree_usage[] = "git tar-tree [--remote=] [basedir]\n" -"*** Note that this command is now deprecated; use git-archive instead."; +"*** Note that this command is now deprecated; use \"git archive\" instead."; int cmd_tar_tree(int argc, const char **argv, const char *prefix) { /* - * git-tar-tree is now a wrapper around git-archive --format=tar + * "git tar-tree" is now a wrapper around "git archive --format=tar" * * $0 --remote= arg... ==> - * git-archive --format=tar --remote= arg... + * git archive --format=tar --remote= arg... * $0 tree-ish ==> - * git-archive --format=tar tree-ish + * git archive --format=tar tree-ish * $0 tree-ish basedir ==> - * git-archive --format-tar --prefix=basedir tree-ish + * git archive --format-tar --prefix=basedir tree-ish */ int i; const char **nargv = xcalloc(sizeof(*nargv), argc + 2); @@ -53,8 +53,8 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix) nargv[nargc] = NULL; fprintf(stderr, - "*** git-tar-tree is now deprecated.\n" - "*** Running git-archive instead.\n***"); + "*** \"git tar-tree\" is now deprecated.\n" + "*** Running \"git archive\" instead.\n***"); for (i = 0; i < nargc; i++) { fputc(' ', stderr); sq_quote_print(stderr, nargv[i]); diff --git a/builtin-unpack-objects.c b/builtin-unpack-objects.c index a891866665..40b20f26e8 100644 --- a/builtin-unpack-objects.c +++ b/builtin-unpack-objects.c @@ -13,7 +13,7 @@ #include "fsck.h" static int dry_run, quiet, recover, has_errors, strict; -static const char unpack_usage[] = "git-unpack-objects [-n] [-q] [-r] [--strict] < pack-file"; +static const char unpack_usage[] = "git unpack-objects [-n] [-q] [-r] [--strict] < pack-file"; /* We always read in 4kB chunks. */ static unsigned char buffer[4096]; diff --git a/builtin-update-index.c b/builtin-update-index.c index 5637d417aa..9d19c51e8e 100644 --- a/builtin-update-index.c +++ b/builtin-update-index.c @@ -14,7 +14,7 @@ * Default to not allowing changes to the list of files. The * tool doesn't actually care, but this makes it harder to add * files to the revision control by mistake by doing something - * like "git-update-index *" and suddenly having all the object + * like "git update-index *" and suddenly having all the object * files be revision controlled. */ static int allow_add; @@ -310,18 +310,18 @@ static void read_index_info(int line_termination) /* This reads lines formatted in one of three formats: * * (1) mode SP sha1 TAB path - * The first format is what "git-apply --index-info" + * The first format is what "git apply --index-info" * reports, and used to reconstruct a partial tree * that is used for phony merge base tree when falling * back on 3-way merge. * * (2) mode SP type SP sha1 TAB path - * The second format is to stuff git-ls-tree output + * The second format is to stuff "git ls-tree" output * into the index file. * * (3) mode SP sha1 SP stage TAB path * This format is to put higher order stages into the - * index file and matches git-ls-files --stage output. + * index file and matches "git ls-files --stage" output. */ errno = 0; ul = strtoul(buf.buf, &ptr, 8); From 1f5a892e5209be329dda316edb0341066d62e3eb Mon Sep 17 00:00:00 2001 From: Heikki Orsila Date: Sat, 13 Sep 2008 19:31:31 +0300 Subject: [PATCH 16/19] Cosmetical command name fix If we came from git.c the first arg would be "archive". "git-archive" isn't a bug because cmd_archive() doesn't check the first arg. Signed-off-by: Heikki Orsila Signed-off-by: Junio C Hamano --- builtin-tar-tree.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin-tar-tree.c b/builtin-tar-tree.c index 419a69b507..0713bca778 100644 --- a/builtin-tar-tree.c +++ b/builtin-tar-tree.c @@ -28,7 +28,7 @@ int cmd_tar_tree(int argc, const char **argv, const char *prefix) char *basedir_arg; int nargc = 0; - nargv[nargc++] = "git-archive"; + nargv[nargc++] = "archive"; nargv[nargc++] = "--format=tar"; if (2 <= argc && !prefixcmp(argv[1], "--remote=")) { From 45e7ca0f0e1042c26d56b578165365c3f70c0121 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 18 Sep 2008 17:40:48 -0500 Subject: [PATCH 17/19] diff.c: return pattern entry pointer rather than just the hunk header pattern This is in preparation for associating a flag with each pattern which will control how the pattern is interpreted. For example, as a basic or extended regular expression. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- diff.c | 55 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/diff.c b/diff.c index 5e01b2bb27..406a76a203 100644 --- a/diff.c +++ b/diff.c @@ -94,32 +94,35 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val * to define a customized regexp to find the beginning of a function to * be used for hunk header lines of "diff -p" style output. */ -static struct funcname_pattern { +struct funcname_pattern_entry { char *name; char *pattern; - struct funcname_pattern *next; +}; +static struct funcname_pattern_list { + struct funcname_pattern_list *next; + struct funcname_pattern_entry e; } *funcname_pattern_list; static int parse_funcname_pattern(const char *var, const char *ep, const char *value) { const char *name; int namelen; - struct funcname_pattern *pp; + struct funcname_pattern_list *pp; name = var + 5; /* "diff." */ namelen = ep - name; for (pp = funcname_pattern_list; pp; pp = pp->next) - if (!strncmp(pp->name, name, namelen) && !pp->name[namelen]) + if (!strncmp(pp->e.name, name, namelen) && !pp->e.name[namelen]) break; if (!pp) { pp = xcalloc(1, sizeof(*pp)); - pp->name = xmemdupz(name, namelen); + pp->e.name = xmemdupz(name, namelen); pp->next = funcname_pattern_list; funcname_pattern_list = pp; } - free(pp->pattern); - pp->pattern = xstrdup(value); + free(pp->e.pattern); + pp->e.pattern = xstrdup(value); return 0; } @@ -1377,20 +1380,17 @@ int diff_filespec_is_binary(struct diff_filespec *one) return one->is_binary; } -static const char *funcname_pattern(const char *ident) +static const struct funcname_pattern_entry *funcname_pattern(const char *ident) { - struct funcname_pattern *pp; + struct funcname_pattern_list *pp; for (pp = funcname_pattern_list; pp; pp = pp->next) - if (!strcmp(ident, pp->name)) - return pp->pattern; + if (!strcmp(ident, pp->e.name)) + return &pp->e; return NULL; } -static struct builtin_funcname_pattern { - const char *name; - const char *pattern; -} builtin_funcname_pattern[] = { +static const struct funcname_pattern_entry builtin_funcname_pattern[] = { { "java", "!^[ ]*\\(catch\\|do\\|for\\|if\\|instanceof\\|" "new\\|return\\|switch\\|throw\\|while\\)\n" "^[ ]*\\(\\([ ]*" @@ -1407,9 +1407,10 @@ static struct builtin_funcname_pattern { { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, }; -static const char *diff_funcname_pattern(struct diff_filespec *one) +static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one) { - const char *ident, *pattern; + const char *ident; + const struct funcname_pattern_entry *pe; int i; diff_filespec_check_attr(one); @@ -1424,9 +1425,9 @@ static const char *diff_funcname_pattern(struct diff_filespec *one) return funcname_pattern("default"); /* Look up custom "funcname.$ident" regexp from config. */ - pattern = funcname_pattern(ident); - if (pattern) - return pattern; + pe = funcname_pattern(ident); + if (pe) + return pe; /* * And define built-in fallback patterns here. Note that @@ -1434,7 +1435,7 @@ static const char *diff_funcname_pattern(struct diff_filespec *one) */ for (i = 0; i < ARRAY_SIZE(builtin_funcname_pattern); i++) if (!strcmp(ident, builtin_funcname_pattern[i].name)) - return builtin_funcname_pattern[i].pattern; + return &builtin_funcname_pattern[i]; return NULL; } @@ -1512,11 +1513,11 @@ static void builtin_diff(const char *name_a, xdemitconf_t xecfg; xdemitcb_t ecb; struct emit_callback ecbdata; - const char *funcname_pattern; + const struct funcname_pattern_entry *pe; - funcname_pattern = diff_funcname_pattern(one); - if (!funcname_pattern) - funcname_pattern = diff_funcname_pattern(two); + pe = diff_funcname_pattern(one); + if (!pe) + pe = diff_funcname_pattern(two); memset(&xecfg, 0, sizeof(xecfg)); memset(&ecbdata, 0, sizeof(ecbdata)); @@ -1528,8 +1529,8 @@ static void builtin_diff(const char *name_a, xpp.flags = XDF_NEED_MINIMAL | o->xdl_opts; xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; - if (funcname_pattern) - xdiff_set_find_func(&xecfg, funcname_pattern); + if (pe) + xdiff_set_find_func(&xecfg, pe->pattern); if (!diffopts) ; else if (!prefixcmp(diffopts, "--unified=")) From a013585b20ac757b0e75a72181ffa44674f35235 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 18 Sep 2008 17:42:48 -0500 Subject: [PATCH 18/19] diff.c: associate a flag with each pattern and use it for compiling regex This is in preparation for allowing extended regular expression patterns. Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- diff.c | 21 ++++++++++++--------- xdiff-interface.c | 4 ++-- xdiff-interface.h | 2 +- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/diff.c b/diff.c index 406a76a203..6881cf4efa 100644 --- a/diff.c +++ b/diff.c @@ -97,13 +97,14 @@ static int parse_lldiff_command(const char *var, const char *ep, const char *val struct funcname_pattern_entry { char *name; char *pattern; + int cflags; }; static struct funcname_pattern_list { struct funcname_pattern_list *next; struct funcname_pattern_entry e; } *funcname_pattern_list; -static int parse_funcname_pattern(const char *var, const char *ep, const char *value) +static int parse_funcname_pattern(const char *var, const char *ep, const char *value, int cflags) { const char *name; int namelen; @@ -123,6 +124,7 @@ static int parse_funcname_pattern(const char *var, const char *ep, const char *v } free(pp->e.pattern); pp->e.pattern = xstrdup(value); + pp->e.cflags = cflags; return 0; } @@ -185,7 +187,8 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) if (!strcmp(ep, ".funcname")) { if (!value) return config_error_nonbool(var); - return parse_funcname_pattern(var, ep, value); + return parse_funcname_pattern(var, ep, value, + 0); } } } @@ -1395,16 +1398,16 @@ static const struct funcname_pattern_entry builtin_funcname_pattern[] = { "new\\|return\\|switch\\|throw\\|while\\)\n" "^[ ]*\\(\\([ ]*" "[A-Za-z_][A-Za-z_0-9]*\\)\\{2,\\}" - "[ ]*([^;]*\\)$" }, + "[ ]*([^;]*\\)$", 0 }, { "pascal", "^\\(\\(procedure\\|function\\|constructor\\|" "destructor\\|interface\\|implementation\\|" "initialization\\|finalization\\)[ \t]*.*\\)$" "\\|" - "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$" - }, - { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$" }, - { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$" }, - { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$" }, + "^\\(.*=[ \t]*\\(class\\|record\\).*\\)$", + 0 }, + { "bibtex", "\\(@[a-zA-Z]\\{1,\\}[ \t]*{\\{0,1\\}[ \t]*[^ \t\"@',\\#}{~%]*\\).*$", 0 }, + { "tex", "^\\(\\\\\\(\\(sub\\)*section\\|chapter\\|part\\)\\*\\{0,1\\}{.*\\)$", 0 }, + { "ruby", "^\\s*\\(\\(class\\|module\\|def\\)\\s.*\\)$", 0 }, }; static const struct funcname_pattern_entry *diff_funcname_pattern(struct diff_filespec *one) @@ -1530,7 +1533,7 @@ static void builtin_diff(const char *name_a, xecfg.ctxlen = o->context; xecfg.flags = XDL_EMIT_FUNCNAMES; if (pe) - xdiff_set_find_func(&xecfg, pe->pattern); + xdiff_set_find_func(&xecfg, pe->pattern, pe->cflags); if (!diffopts) ; else if (!prefixcmp(diffopts, "--unified=")) diff --git a/xdiff-interface.c b/xdiff-interface.c index 61dc5c5470..2c81f40cb6 100644 --- a/xdiff-interface.c +++ b/xdiff-interface.c @@ -206,7 +206,7 @@ static long ff_regexp(const char *line, long len, return result; } -void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) +void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value, int cflags) { int i; struct ff_regs *regs; @@ -231,7 +231,7 @@ void xdiff_set_find_func(xdemitconf_t *xecfg, const char *value) expression = buffer = xstrndup(value, ep - value); else expression = value; - if (regcomp(®->re, expression, 0)) + if (regcomp(®->re, expression, cflags)) die("Invalid regexp to look for hunk header: %s", expression); free(buffer); value = ep + 1; diff --git a/xdiff-interface.h b/xdiff-interface.h index f7f791d96b..33cab9dd59 100644 --- a/xdiff-interface.h +++ b/xdiff-interface.h @@ -21,6 +21,6 @@ int parse_hunk_header(char *line, int len, int read_mmfile(mmfile_t *ptr, const char *filename); int buffer_is_binary(const char *ptr, unsigned long size); -extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line); +extern void xdiff_set_find_func(xdemitconf_t *xecfg, const char *line, int cflags); #endif From 45d9414fa5599b41578625961b53e18a9b9148c7 Mon Sep 17 00:00:00 2001 From: Brandon Casey Date: Thu, 18 Sep 2008 17:44:33 -0500 Subject: [PATCH 19/19] diff.*.xfuncname which uses "extended" regex's for hunk header selection Currently, the hunk headers produced by 'diff -p' are customizable by setting the diff.*.funcname option in the config file. The 'funcname' option takes a basic regular expression. This functionality was designed using the GNU regex library which, by default, allows using backslashed versions of some extended regular expression operators, even in Basic Regular Expression mode. For example, the following characters, when backslashed, are interpreted according to the extended regular expression rules: ?, +, and |. As such, the builtin funcname patterns were created using some extended regular expression operators. Other platforms which adhere more strictly to the POSIX spec do not interpret the backslashed extended RE operators in Basic Regular Expression mode. This causes the pattern matching for the builtin funcname patterns to fail on those platforms. Introduce a new option 'xfuncname' which uses extended regular expressions, and advertise it _instead_ of funcname. Since most users are on GNU platforms, the majority of funcname patterns are created and tested there. Advertising only xfuncname should help to avoid the creation of non-portable patterns which work with GNU regex but not elsewhere. Additionally, the extended regular expressions may be less ugly and complicated compared to the basic RE since many common special operators do not need to be backslashed. For example, the GNU Basic RE: ^[ ]*\\(\\(public\\|static\\).*\\)$ becomes the following Extended RE: ^[ ]*((public|static).*)$ Signed-off-by: Brandon Casey Signed-off-by: Junio C Hamano --- Documentation/gitattributes.txt | 4 ++-- diff.c | 5 +++++ t/t4018-diff-funcname.sh | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 94e6752aa2..9259637609 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -288,13 +288,13 @@ for paths. *.tex diff=tex ------------------------ -Then, you would define "diff.tex.funcname" configuration to +Then, you would define "diff.tex.xfuncname" configuration to specify a regular expression that matches a line that you would want to appear as the hunk header, like this: ------------------------ [diff "tex"] - funcname = "^\\(\\\\\\(sub\\)*section{.*\\)$" + xfuncname = "^(\\\\(sub)*section\\{.*)$" ------------------------ Note. A single level of backslashes are eaten by the diff --git a/diff.c b/diff.c index 6881cf4efa..dabb4b4a02 100644 --- a/diff.c +++ b/diff.c @@ -189,6 +189,11 @@ int git_diff_basic_config(const char *var, const char *value, void *cb) return config_error_nonbool(var); return parse_funcname_pattern(var, ep, value, 0); + } else if (!strcmp(ep, ".xfuncname")) { + if (!value) + return config_error_nonbool(var); + return parse_funcname_pattern(var, ep, value, + REG_EXTENDED); } } } diff --git a/t/t4018-diff-funcname.sh b/t/t4018-diff-funcname.sh index 18bcd9713d..602d68f092 100755 --- a/t/t4018-diff-funcname.sh +++ b/t/t4018-diff-funcname.sh @@ -58,7 +58,7 @@ test_expect_success 'last regexp must not be negated' ' ' test_expect_success 'alternation in pattern' ' - git config diff.java.funcname "^[ ]*\\(\\(public\\|static\\).*\\)$" + git config diff.java.xfuncname "^[ ]*((public|static).*)$" && git diff --no-index Beer.java Beer-correct.java | grep "^@@.*@@ public static void main(" '