From: Junio C Hamano Date: Tue, 16 May 2006 01:09:15 +0000 (-0700) Subject: Merge branch 'lt/diff' X-Git-Tag: v1.4.0-rc1~143 X-Git-Url: https://git.lorimer.id.au/gitweb.git/diff_plain/05f743f328e56780fb86c57da65f41df6e3b19a3?hp=ee1e5412a702674d4da95a4aef73a73d2834dcc3 Merge branch 'lt/diff' * lt/diff: git diff: support "-U" and "--unified" options properly --- diff --git a/Makefile b/Makefile index 37fbe789d3..f4b6ef8751 100644 --- a/Makefile +++ b/Makefile @@ -131,7 +131,8 @@ SCRIPT_PERL = \ git-archimport.perl git-cvsimport.perl git-relink.perl \ git-shortlog.perl git-fmt-merge-msg.perl git-rerere.perl \ git-annotate.perl git-cvsserver.perl \ - git-svnimport.perl git-mv.perl git-cvsexportcommit.perl + git-svnimport.perl git-mv.perl git-cvsexportcommit.perl \ + git-send-email.perl SCRIPT_PYTHON = \ git-merge-recursive.py @@ -285,7 +286,9 @@ ifeq ($(uname_S),OpenBSD) ALL_LDFLAGS += -L/usr/local/lib endif ifeq ($(uname_S),NetBSD) - NEEDS_LIBICONV = YesPlease + ifeq ($(shell expr "$(uname_R)" : '[01]\.'),2) + NEEDS_LIBICONV = YesPlease + endif ALL_CFLAGS += -I/usr/pkg/include ALL_LDFLAGS += -L/usr/pkg/lib -Wl,-rpath,/usr/pkg/lib endif @@ -319,10 +322,6 @@ else endif endif -ifdef WITH_SEND_EMAIL - SCRIPT_PERL += git-send-email.perl -endif - ifndef NO_CURL ifdef CURLDIR # This is still problematic -- gcc does not always want -R. diff --git a/config.c b/config.c index 0f518c957c..0248c6d8a5 100644 --- a/config.c +++ b/config.c @@ -134,6 +134,41 @@ static int get_value(config_fn_t fn, char *name, unsigned int len) return fn(name, value); } +static int get_extended_base_var(char *name, int baselen, int c) +{ + do { + if (c == '\n') + return -1; + c = get_next_char(); + } while (isspace(c)); + + /* We require the format to be '[base "extension"]' */ + if (c != '"') + return -1; + name[baselen++] = '.'; + + for (;;) { + int c = get_next_char(); + if (c == '\n') + return -1; + if (c == '"') + break; + if (c == '\\') { + c = get_next_char(); + if (c == '\n') + return -1; + } + name[baselen++] = c; + if (baselen > MAXNAME / 2) + return -1; + } + + /* Final ']' */ + if (get_next_char() != ']') + return -1; + return baselen; +} + static int get_base_var(char *name) { int baselen = 0; @@ -144,6 +179,8 @@ static int get_base_var(char *name) return -1; if (c == ']') return baselen; + if (isspace(c)) + return get_extended_base_var(name, baselen, c); if (!isalnum(c) && c != '.') return -1; if (baselen > MAXNAME / 2) @@ -335,10 +372,12 @@ static int store_aux(const char* key, const char* value) store.offset[store.seen] = ftell(config_file); store.state = KEY_SEEN; store.seen++; - } else if (strrchr(key, '.') - key == store.baselen && + } else { + if (strrchr(key, '.') - key == store.baselen && !strncmp(key, store.key, store.baselen)) { store.state = SECTION_SEEN; store.offset[store.seen] = ftell(config_file); + } } } return 0; @@ -346,8 +385,30 @@ static int store_aux(const char* key, const char* value) static void store_write_section(int fd, const char* key) { + const char *dot = strchr(key, '.'); + int len1 = store.baselen, len2 = -1; + + dot = strchr(key, '.'); + if (dot) { + int dotlen = dot - key; + if (dotlen < len1) { + len2 = len1 - dotlen - 1; + len1 = dotlen; + } + } + write(fd, "[", 1); - write(fd, key, store.baselen); + write(fd, key, len1); + if (len2 >= 0) { + write(fd, " \"", 2); + while (--len2 >= 0) { + unsigned char c = *++dot; + if (c == '"') + write(fd, "\\", 1); + write(fd, &c, 1); + } + write(fd, "\"", 1); + } write(fd, "]\n", 2); } @@ -421,7 +482,7 @@ int git_config_set(const char* key, const char* value) int git_config_set_multivar(const char* key, const char* value, const char* value_regex, int multi_replace) { - int i; + int i, dot; int fd = -1, in_fd; int ret; char* config_filename = strdup(git_path("config")); @@ -446,16 +507,23 @@ int git_config_set_multivar(const char* key, const char* value, * Validate the key and while at it, lower case it for matching. */ store.key = (char*)malloc(strlen(key)+1); - for (i = 0; key[i]; i++) - if (i != store.baselen && - ((!isalnum(key[i]) && key[i] != '.') || - (i == store.baselen+1 && !isalpha(key[i])))) { - fprintf(stderr, "invalid key: %s\n", key); - free(store.key); - ret = 1; - goto out_free; - } else - store.key[i] = tolower(key[i]); + dot = 0; + for (i = 0; key[i]; i++) { + unsigned char c = key[i]; + if (c == '.') + dot = 1; + /* Leave the extended basename untouched.. */ + if (!dot || i > store.baselen) { + if (!isalnum(c) || (i == store.baselen+1 && !isalpha(c))) { + fprintf(stderr, "invalid key: %s\n", key); + free(store.key); + ret = 1; + goto out_free; + } + c = tolower(c); + } + store.key[i] = c; + } store.key[i] = 0; /* diff --git a/diff.c b/diff.c index be925a3a39..1bdaba2f77 100644 --- a/diff.c +++ b/diff.c @@ -232,11 +232,16 @@ static char *pprint_rename(const char *a, const char *b) * name-a => name-b */ if (pfx_length + sfx_length) { + int a_midlen = len_a - pfx_length - sfx_length; + int b_midlen = len_b - pfx_length - sfx_length; + if (a_midlen < 0) a_midlen = 0; + if (b_midlen < 0) b_midlen = 0; + name = xmalloc(len_a + len_b - pfx_length - sfx_length + 7); sprintf(name, "%.*s{%.*s => %.*s}%s", pfx_length, a, - len_a - pfx_length - sfx_length, a + pfx_length, - len_b - pfx_length - sfx_length, b + pfx_length, + a_midlen, a + pfx_length, + b_midlen, b + pfx_length, a + len_a - sfx_length); } else { diff --git a/git-commit.sh b/git-commit.sh index 26cd7ca54d..6ef1a9dedc 100755 --- a/git-commit.sh +++ b/git-commit.sh @@ -640,6 +640,8 @@ case "$no_edit" in exit 1 ;; esac + git-var GIT_AUTHOR_IDENT > /dev/null || die + git-var GIT_COMMITTER_IDENT > /dev/null || die ${VISUAL:-${EDITOR:-vi}} "$GIT_DIR/COMMIT_EDITMSG" ;; esac diff --git a/git-send-email.perl b/git-send-email.perl index 703dd1ff9e..d8c4b1f892 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -89,6 +89,41 @@ sub gitvar_ident { my ($author) = gitvar_ident('GIT_AUTHOR_IDENT'); my ($committer) = gitvar_ident('GIT_COMMITTER_IDENT'); +my %aliases; +chomp(my @alias_files = `git-repo-config --get-all sendemail.aliasesfile`); +chomp(my $aliasfiletype = `git-repo-config sendemail.aliasfiletype`); +my %parse_alias = ( + # multiline formats can be supported in the future + mutt => sub { my $fh = shift; while (<$fh>) { + if (/^alias\s+(\S+)\s+(.*)$/) { + my ($alias, $addr) = ($1, $2); + $addr =~ s/#.*$//; # mutt allows # comments + # commas delimit multiple addresses + $aliases{$alias} = [ split(/\s*,\s*/, $addr) ]; + }}}, + mailrc => sub { my $fh = shift; while (<$fh>) { + if (/^alias\s+(\S+)\s+(.*)$/) { + # spaces delimit multiple addresses + $aliases{$1} = [ split(/\s+/, $2) ]; + }}}, + pine => sub { my $fh = shift; while (<$fh>) { + if (/^(\S+)\s+(.*)$/) { + $aliases{$1} = [ split(/\s*,\s*/, $2) ]; + }}}, + gnus => sub { my $fh = shift; while (<$fh>) { + if (/\(define-mail-alias\s+"(\S+?)"\s+"(\S+?)"\)/) { + $aliases{$1} = [ $2 ]; + }}} +); + +if (@alias_files && defined $parse_alias{$aliasfiletype}) { + foreach my $file (@alias_files) { + open my $fh, '<', $file or die "opening $file: $!\n"; + $parse_alias{$aliasfiletype}->($fh); + close $fh; + } +} + my $prompting = 0; if (!defined $from) { $from = $author || $committer; @@ -112,6 +147,19 @@ sub gitvar_ident { $prompting++; } +sub expand_aliases { + my @cur = @_; + my @last; + do { + @last = @cur; + @cur = map { $aliases{$_} ? @{$aliases{$_}} : $_ } @last; + } while (join(',',@cur) ne join(',',@last)); + return @cur; +} + +@to = expand_aliases(@to); +@initial_cc = expand_aliases(@initial_cc); + if (!defined $initial_subject && $compose) { do { $_ = $term->readline("What subject should the emails start with? ", diff --git a/git.spec.in b/git.spec.in index 96dfc1de55..8ccd2564e7 100644 --- a/git.spec.in +++ b/git.spec.in @@ -74,12 +74,12 @@ Git revision tree visualiser ('gitk') %setup -q %build -make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease WITH_SEND_EMAIL=1 \ +make %{_smp_mflags} CFLAGS="$RPM_OPT_FLAGS" WITH_OWN_SUBPROCESS_PY=YesPlease \ prefix=%{_prefix} all %{!?_without_docs: doc} %install rm -rf $RPM_BUILD_ROOT -make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease WITH_SEND_EMAIL=1 \ +make %{_smp_mflags} DESTDIR=$RPM_BUILD_ROOT WITH_OWN_SUBPROCESS_PY=YesPlease \ prefix=%{_prefix} mandir=%{_mandir} \ install %{!?_without_docs: install-doc} diff --git a/pack-objects.c b/pack-objects.c index 5466b15167..0dbda2cd9f 100644 --- a/pack-objects.c +++ b/pack-objects.c @@ -10,7 +10,6 @@ #include "tree-walk.h" #include #include -#include static const char pack_usage[] = "git-pack-objects [-q] [--no-reuse-delta] [--non-empty] [--local] [--incremental] [--window=N] [--depth=N] {--stdout | base-name} < object-list"; @@ -157,7 +156,7 @@ static void prepare_pack_revindex(struct pack_revindex *rix) rix->revindex = xmalloc(sizeof(unsigned long) * (num_ent + 1)); for (i = 0; i < num_ent; i++) { - uint32_t hl = *((uint32_t *)(index + 24 * i)); + unsigned int hl = *((unsigned int *)(index + 24 * i)); rix->revindex[i] = ntohl(hl); } /* This knows the pack format -- the 20-byte trailer diff --git a/repo-config.c b/repo-config.c index 63eda1bb78..284af2273c 100644 --- a/repo-config.c +++ b/repo-config.c @@ -65,11 +65,13 @@ static int show_config(const char* key_, const char* value_) static int get_value(const char* key_, const char* regex_) { int i; + char *tl; - key = malloc(strlen(key_)+1); - for (i = 0; key_[i]; i++) - key[i] = tolower(key_[i]); - key[i] = 0; + key = strdup(key_); + for (tl=key+strlen(key)-1; tl >= key && *tl != '.'; --tl) + *tl = tolower(*tl); + for (tl=key; *tl && *tl != '.'; ++tl) + *tl = tolower(*tl); if (use_key_regexp) { key_regexp = (regex_t*)malloc(sizeof(regex_t)); diff --git a/sha1_file.c b/sha1_file.c index 3372ebcdca..223001033c 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -13,7 +13,6 @@ #include "commit.h" #include "tag.h" #include "tree.h" -#include #ifndef O_NOATIME #if defined(__linux__) && (defined(__i386__) || defined(__PPC__)) @@ -1162,7 +1161,7 @@ int find_pack_entry_one(const unsigned char *sha1, int mi = (lo + hi) / 2; int cmp = memcmp(index + 24 * mi + 4, sha1, 20); if (!cmp) { - e->offset = ntohl(*((uint32_t *)(index + 24 * mi))); + e->offset = ntohl(*((unsigned int *)(index + 24 * mi))); memcpy(e->sha1, sha1, 20); e->p = p; return 1; diff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh index 7090ea92c1..8260d57b63 100755 --- a/t/t1300-repo-config.sh +++ b/t/t1300-repo-config.sh @@ -229,7 +229,7 @@ test_expect_failure 'invalid key' 'git-repo-config inval.2key blabla' test_expect_success 'correct key' 'git-repo-config 123456.a123 987' test_expect_success 'hierarchical section' \ - 'git-repo-config 1.2.3.alpha beta' + 'git-repo-config Version.1.2.3eX.Alpha beta' cat > expect << EOF [beta] ; silly comment # another comment @@ -241,8 +241,8 @@ noIndent= sillyValue ; 'nother silly comment NoNewLine = wow2 for me [123456] a123 = 987 -[1.2.3] - alpha = beta +[Version "1.2.3eX"] + Alpha = beta EOF test_expect_success 'hierarchical section value' 'cmp .git/config expect' @@ -251,7 +251,7 @@ cat > expect << EOF beta.noindent=sillyValue nextsection.nonewline=wow2 for me 123456.a123=987 -1.2.3.alpha=beta +version.1.2.3eX.alpha=beta EOF test_expect_success 'working --list' \