From: Junio C Hamano Date: Wed, 18 Oct 2017 05:19:11 +0000 (+0900) Subject: Merge branch 'hn/typofix' into maint X-Git-Tag: v2.15.0-rc2~5^2~18 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=9554e71f60a0ac49a93b2ec8003a652ed65b05b5;hp=217bb56d4f32f1637b40fcf53237586f0ec27c15;p=thirdparty%2Fgit.git Merge branch 'hn/typofix' into maint * hn/typofix: submodule.h: typofix --- diff --git a/Documentation/RelNotes/2.10.5.txt b/Documentation/RelNotes/2.10.5.txt new file mode 100644 index 0000000000..a498fd6fdc --- /dev/null +++ b/Documentation/RelNotes/2.10.5.txt @@ -0,0 +1,17 @@ +Git v2.10.5 Release Notes +========================= + +Fixes since v2.10.4 +------------------- + + * "git cvsserver" no longer is invoked by "git daemon" by default, + as it is old and largely unmaintained. + + * Various Perl scripts did not use safe_pipe_capture() instead of + backticks, leaving them susceptible to end-user input. They have + been corrected. + +Credits go to joernchen for finding the +unsafe constructs in "git cvsserver", and to Jeff King at GitHub for +finding and fixing instances of the same issue in other scripts. + diff --git a/Documentation/RelNotes/2.11.4.txt b/Documentation/RelNotes/2.11.4.txt new file mode 100644 index 0000000000..ad4da8eb09 --- /dev/null +++ b/Documentation/RelNotes/2.11.4.txt @@ -0,0 +1,17 @@ +Git v2.11.4 Release Notes +========================= + +Fixes since v2.11.3 +------------------- + + * "git cvsserver" no longer is invoked by "git daemon" by default, + as it is old and largely unmaintained. + + * Various Perl scripts did not use safe_pipe_capture() instead of + backticks, leaving them susceptible to end-user input. They have + been corrected. + +Credits go to joernchen for finding the +unsafe constructs in "git cvsserver", and to Jeff King at GitHub for +finding and fixing instances of the same issue in other scripts. + diff --git a/Documentation/RelNotes/2.12.5.txt b/Documentation/RelNotes/2.12.5.txt new file mode 100644 index 0000000000..8fa73cfce7 --- /dev/null +++ b/Documentation/RelNotes/2.12.5.txt @@ -0,0 +1,17 @@ +Git v2.12.5 Release Notes +========================= + +Fixes since v2.12.4 +------------------- + + * "git cvsserver" no longer is invoked by "git daemon" by default, + as it is old and largely unmaintained. + + * Various Perl scripts did not use safe_pipe_capture() instead of + backticks, leaving them susceptible to end-user input. They have + been corrected. + +Credits go to joernchen for finding the +unsafe constructs in "git cvsserver", and to Jeff King at GitHub for +finding and fixing instances of the same issue in other scripts. + diff --git a/Documentation/RelNotes/2.13.6.txt b/Documentation/RelNotes/2.13.6.txt new file mode 100644 index 0000000000..afcae9c808 --- /dev/null +++ b/Documentation/RelNotes/2.13.6.txt @@ -0,0 +1,17 @@ +Git v2.13.6 Release Notes +========================= + +Fixes since v2.13.5 +------------------- + + * "git cvsserver" no longer is invoked by "git daemon" by default, + as it is old and largely unmaintained. + + * Various Perl scripts did not use safe_pipe_capture() instead of + backticks, leaving them susceptible to end-user input. They have + been corrected. + +Credits go to joernchen for finding the +unsafe constructs in "git cvsserver", and to Jeff King at GitHub for +finding and fixing instances of the same issue in other scripts. + diff --git a/Documentation/RelNotes/2.14.2.txt b/Documentation/RelNotes/2.14.2.txt index bcfe78f59d..bec9186ade 100644 --- a/Documentation/RelNotes/2.14.2.txt +++ b/Documentation/RelNotes/2.14.2.txt @@ -91,4 +91,15 @@ Fixes since v2.14.1 * "git archive" did not work well with pathspecs and the export-ignore attribute. + * "git cvsserver" no longer is invoked by "git daemon" by default, + as it is old and largely unmaintained. + + * Various Perl scripts did not use safe_pipe_capture() instead of + backticks, leaving them susceptible to end-user input. They have + been corrected. + Also contains various documentation updates and code clean-ups. + +Credits go to joernchen for finding the +unsafe constructs in "git cvsserver", and to Jeff King at GitHub for +finding and fixing instances of the same issue in other scripts. diff --git a/Documentation/git-cat-file.txt b/Documentation/git-cat-file.txt index 204541c690..fb09cd69d6 100644 --- a/Documentation/git-cat-file.txt +++ b/Documentation/git-cat-file.txt @@ -192,7 +192,7 @@ newline. The available atoms are: The 40-hex object name of the object. `objecttype`:: - The type of of the object (the same as `cat-file -t` reports). + The type of the object (the same as `cat-file -t` reports). `objectsize`:: The size, in bytes, of the object (the same as `cat-file -s` diff --git a/Documentation/git-checkout.txt b/Documentation/git-checkout.txt index d6399c0af8..bd268a8fcc 100644 --- a/Documentation/git-checkout.txt +++ b/Documentation/git-checkout.txt @@ -38,7 +38,7 @@ $ git checkout -b --track / ------------ + You could omit , in which case the command degenerates to -"check out the current branch", which is a glorified no-op with a +"check out the current branch", which is a glorified no-op with rather expensive side-effects to show only the tracking information, if exists, for the current branch. diff --git a/Documentation/git-for-each-ref.txt b/Documentation/git-for-each-ref.txt index bb370c9c7b..66b4e0a405 100644 --- a/Documentation/git-for-each-ref.txt +++ b/Documentation/git-for-each-ref.txt @@ -10,8 +10,9 @@ SYNOPSIS [verse] 'git for-each-ref' [--count=] [--shell|--perl|--python|--tcl] [(--sort=)...] [--format=] [...] - [--points-at ] [(--merged | --no-merged) []] - [--contains []] [--no-contains []] + [--points-at=] + (--merged[=] | --no-merged[=]) + [--contains[=]] [--no-contains[=]] DESCRIPTION ----------- @@ -25,19 +26,25 @@ host language allowing their direct evaluation in that language. OPTIONS ------- -:: +...:: + If one or more patterns are given, only refs are shown that + match against at least one pattern, either using fnmatch(3) or + literally, in the latter case matching completely or from the + beginning up to a slash. + +--count=:: By default the command shows all refs that match ``. This option makes it stop after showing that many refs. -:: +--sort=:: A field name to sort on. Prefix `-` to sort in descending order of the value. When unspecified, `refname` is used. You may use the --sort= option multiple times, in which case the last key becomes the primary key. -:: +--format=:: A string that interpolates `%(fieldname)` from a ref being shown and the object it points at. If `fieldname` is prefixed with an asterisk (`*`) and the ref points @@ -50,12 +57,6 @@ OPTIONS `xx`; for example `%00` interpolates to `\0` (NUL), `%09` to `\t` (TAB) and `%0a` to `\n` (LF). -...:: - If one or more patterns are given, only refs are shown that - match against at least one pattern, either using fnmatch(3) or - literally, in the latter case matching completely or from the - beginning up to a slash. - --shell:: --perl:: --python:: @@ -65,24 +66,24 @@ OPTIONS the specified host language. This is meant to produce a scriptlet that can directly be `eval`ed. ---points-at :: +--points-at=:: Only list refs which points at the given object. ---merged []:: +--merged[=]:: Only list refs whose tips are reachable from the specified commit (HEAD if not specified), incompatible with `--no-merged`. ---no-merged []:: +--no-merged[=]:: Only list refs whose tips are not reachable from the specified commit (HEAD if not specified), incompatible with `--merged`. ---contains []:: +--contains[=]:: Only list refs which contain the specified commit (HEAD if not specified). ---no-contains []:: +--no-contains[=]:: Only list refs which don't contain the specified commit (HEAD if not specified). diff --git a/Documentation/git-notes.txt b/Documentation/git-notes.txt index be7db3048d..43677297f3 100644 --- a/Documentation/git-notes.txt +++ b/Documentation/git-notes.txt @@ -171,7 +171,7 @@ OPTIONS object that does not have notes attached to it. --stdin:: - Also read the object names to remove notes from from the standard + Also read the object names to remove notes from the standard input (there is no reason you cannot combine this with object names from the command line). diff --git a/Documentation/git-shell.txt b/Documentation/git-shell.txt index 2e30a3e42d..54cf2560be 100644 --- a/Documentation/git-shell.txt +++ b/Documentation/git-shell.txt @@ -79,6 +79,22 @@ EOF $ chmod +x $HOME/git-shell-commands/no-interactive-login ---------------- +To enable git-cvsserver access (which should generally have the +`no-interactive-login` example above as a prerequisite, as creating +the git-shell-commands directory allows interactive logins): + +---------------- +$ cat >$HOME/git-shell-commands/cvs <<\EOF +if ! test $# = 1 && test "$1" = "server" +then + echo >&2 "git-cvsserver only handles \"server\"" + exit 1 +fi +exec git cvsserver server +EOF +$ chmod +x $HOME/git-shell-commands/cvs +---------------- + SEE ALSO -------- ssh(1), diff --git a/Documentation/git-update-index.txt b/Documentation/git-update-index.txt index 1579abf3c3..a14e6aebd9 100644 --- a/Documentation/git-update-index.txt +++ b/Documentation/git-update-index.txt @@ -153,7 +153,7 @@ you will need to handle the situation manually. + Version 4 performs a simple pathname compression that reduces index size by 30%-50% on large repositories, which results in faster load -time. Version 4 is relatively young (first released in in 1.8.0 in +time. Version 4 is relatively young (first released in 1.8.0 in October 2012). Other Git implementations such as JGit and libgit2 may not support it yet. diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index c4f2be2542..4c68bc19d5 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -151,7 +151,10 @@ unspecified. This attribute sets a specific line-ending style to be used in the working directory. It enables end-of-line conversion without any -content checks, effectively setting the `text` attribute. +content checks, effectively setting the `text` attribute. Note that +setting this attribute on paths which are in the index with CRLF line +endings may make the paths to be considered dirty. Adding the path to +the index again will normalize the line endings in the index. Set to string value "crlf":: diff --git a/Documentation/merge-strategies.txt b/Documentation/merge-strategies.txt index 2eb92b9327..a09d597463 100644 --- a/Documentation/merge-strategies.txt +++ b/Documentation/merge-strategies.txt @@ -39,7 +39,8 @@ even look at what the other tree contains at all. It discards everything the other tree did, declaring 'our' history contains all that happened in it. theirs;; - This is the opposite of 'ours'. + This is the opposite of 'ours'; note that, unlike 'ours', there is + no 'theirs' merge stragegy to confuse this merge option with. patience;; With this option, 'merge-recursive' spends a little extra time diff --git a/archive.c b/archive.c index 2ad7e6cb90..f81bd3649a 100644 --- a/archive.c +++ b/archive.c @@ -121,11 +121,6 @@ static int check_attr_export_subst(const struct attr_check *check) return check && ATTR_TRUE(check->items[1].value); } -static int should_queue_directories(const struct archiver_args *args) -{ - return args->pathspec.has_wildcard; -} - static int write_archive_entry(const unsigned char *sha1, const char *base, int baselen, const char *filename, unsigned mode, int stage, void *context) @@ -147,7 +142,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base, strbuf_addch(&path, '/'); path_without_prefix = path.buf + args->baselen; - if (!S_ISDIR(mode) || !should_queue_directories(args)) { + if (!S_ISDIR(mode)) { const struct attr_check *check; check = get_archive_attrs(path_without_prefix); if (check_attr_export_ignore(check)) @@ -169,14 +164,6 @@ static int write_archive_entry(const unsigned char *sha1, const char *base, return write_entry(args, sha1, path.buf, path.len, mode); } -static int write_archive_entry_buf(const unsigned char *sha1, struct strbuf *base, - const char *filename, unsigned mode, int stage, - void *context) -{ - return write_archive_entry(sha1, base->buf, base->len, - filename, mode, stage, context); -} - static void queue_directory(const unsigned char *sha1, struct strbuf *base, const char *filename, unsigned mode, int stage, struct archiver_context *c) @@ -290,9 +277,7 @@ int write_archive_entries(struct archiver_args *args, } err = read_tree_recursive(args->tree, "", 0, 0, &args->pathspec, - should_queue_directories(args) ? - queue_or_write_archive_entry : - write_archive_entry_buf, + queue_or_write_archive_entry, &context); if (err == READ_TREE_RECURSIVE) err = 0; diff --git a/builtin/cat-file.c b/builtin/cat-file.c index 96b786e489..188ddc3e50 100644 --- a/builtin/cat-file.c +++ b/builtin/cat-file.c @@ -96,7 +96,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, return !has_object_file(&oid); case 'w': - if (!path[0]) + if (!path) die("git cat-file --filters %s: must be " "", obj_name); @@ -106,7 +106,7 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name, break; case 'c': - if (!path[0]) + if (!path) die("git cat-file --textconv %s: must be ", obj_name); diff --git a/builtin/commit-tree.c b/builtin/commit-tree.c index a4a923d7c0..c1de41c67f 100644 --- a/builtin/commit-tree.c +++ b/builtin/commit-tree.c @@ -102,7 +102,6 @@ int cmd_commit_tree(int argc, const char **argv, const char *prefix) if (fd && close(fd)) die_errno("git commit-tree: failed to close '%s'", argv[i]); - strbuf_complete_line(&buffer); continue; } diff --git a/builtin/describe.c b/builtin/describe.c index 89ea1cdd60..94ff2fba0b 100644 --- a/builtin/describe.c +++ b/builtin/describe.c @@ -155,18 +155,21 @@ static int get_name(const char *path, const struct object_id *oid, int flag, voi * pattern. */ if (patterns.nr) { + int found = 0; struct string_list_item *item; if (!is_tag) return 0; for_each_string_list_item(item, &patterns) { - if (!wildmatch(item->string, path + 10, 0)) + if (!wildmatch(item->string, path + 10, 0)) { + found = 1; break; + } + } - /* If we get here, no pattern matched. */ + if (!found) return 0; - } } /* Is it annotated? */ diff --git a/builtin/gc.c b/builtin/gc.c index e6b84475ae..53c19be8b2 100644 --- a/builtin/gc.c +++ b/builtin/gc.c @@ -257,7 +257,7 @@ static const char *lock_repo_for_gc(int force, pid_t* ret_pid) int should_exit; if (!scan_fmt) - scan_fmt = xstrfmt("%s %%%dc", "%"SCNuMAX, HOST_NAME_MAX); + scan_fmt = xstrfmt("%s %%%ds", "%"SCNuMAX, HOST_NAME_MAX); fp = fopen(pidfile_path, "r"); memset(locking_host, 0, sizeof(locking_host)); should_exit = diff --git a/builtin/name-rev.c b/builtin/name-rev.c index c41ea7c2a6..598da6c8bc 100644 --- a/builtin/name-rev.c +++ b/builtin/name-rev.c @@ -253,7 +253,7 @@ static int name_ref(const char *path, const struct object_id *oid, int flags, vo struct commit *commit = (struct commit *)o; int from_tag = starts_with(path, "refs/tags/"); - if (taggerdate == ULONG_MAX) + if (taggerdate == TIME_MAX) taggerdate = ((struct commit *)o)->date; path = name_ref_abbrev(path, can_abbreviate_output); name_rev(commit, xstrdup(path), taggerdate, 0, 0, diff --git a/builtin/rev-parse.c b/builtin/rev-parse.c index c78b7b33d6..7f965fe74e 100644 --- a/builtin/rev-parse.c +++ b/builtin/rev-parse.c @@ -757,8 +757,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix) continue; } if (!strcmp(arg, "--bisect")) { - for_each_ref_in("refs/bisect/bad", show_reference, NULL); - for_each_ref_in("refs/bisect/good", anti_reference, NULL); + for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0); + for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0); continue; } if (opt_with_value(arg, "--branches", &arg)) { diff --git a/compat/poll/poll.c b/compat/poll/poll.c index b10adc780f..ae03b74a6f 100644 --- a/compat/poll/poll.c +++ b/compat/poll/poll.c @@ -438,6 +438,10 @@ poll (struct pollfd *pfd, nfds_t nfd, int timeout) pfd[i].revents = happened; rc++; } + else + { + pfd[i].revents = 0; + } } return rc; diff --git a/config.c b/config.c index acebc85d81..c138c0ba05 100644 --- a/config.c +++ b/config.c @@ -2404,7 +2404,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, { int fd = -1, in_fd = -1; int ret; - struct lock_file *lock = NULL; + static struct lock_file lock; char *filename_buf = NULL; char *contents = NULL; size_t contents_sz; @@ -2423,8 +2423,7 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, * The lock serves a purpose in addition to locking: the new * contents of .git/config will be written into it. */ - lock = xcalloc(1, sizeof(struct lock_file)); - fd = hold_lock_file_for_update(lock, config_filename, 0); + fd = hold_lock_file_for_update(&lock, config_filename, 0); if (fd < 0) { error_errno("could not lock config file %s", config_filename); free(store.key); @@ -2537,8 +2536,8 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, close(in_fd); in_fd = -1; - if (chmod(get_lock_file_path(lock), st.st_mode & 07777) < 0) { - error_errno("chmod on %s failed", get_lock_file_path(lock)); + if (chmod(get_lock_file_path(&lock), st.st_mode & 07777) < 0) { + error_errno("chmod on %s failed", get_lock_file_path(&lock)); ret = CONFIG_NO_WRITE; goto out_free; } @@ -2593,28 +2592,19 @@ int git_config_set_multivar_in_file_gently(const char *config_filename, contents = NULL; } - if (commit_lock_file(lock) < 0) { + if (commit_lock_file(&lock) < 0) { error_errno("could not write config file %s", config_filename); ret = CONFIG_NO_WRITE; - lock = NULL; goto out_free; } - /* - * lock is committed, so don't try to roll it back below. - * NOTE: Since lockfile.c keeps a linked list of all created - * lock_file structures, it isn't safe to free(lock). It's - * better to just leave it hanging around. - */ - lock = NULL; ret = 0; /* Invalidate the config cache */ git_config_clear(); out_free: - if (lock) - rollback_lock_file(lock); + rollback_lock_file(&lock); free(filename_buf); if (contents) munmap(contents, contents_sz); @@ -2623,7 +2613,7 @@ out_free: return ret; write_err_out: - ret = write_error(get_lock_file_path(lock)); + ret = write_error(get_lock_file_path(&lock)); goto out_free; } diff --git a/contrib/diff-highlight/Makefile b/contrib/diff-highlight/Makefile index fbf5c58249..f2be7cc924 100644 --- a/contrib/diff-highlight/Makefile +++ b/contrib/diff-highlight/Makefile @@ -17,4 +17,7 @@ shebang.perl: FORCE test: all $(MAKE) -C t +clean: + $(RM) diff-highlight + .PHONY: FORCE diff --git a/exec_cmd.c b/exec_cmd.c index fb94aeba9c..ce192a2d64 100644 --- a/exec_cmd.c +++ b/exec_cmd.c @@ -5,21 +5,14 @@ #define MAX_ARGS 32 static const char *argv_exec_path; + +#ifdef RUNTIME_PREFIX static const char *argv0_path; -char *system_path(const char *path) +static const char *system_prefix(void) { -#ifdef RUNTIME_PREFIX static const char *prefix; -#else - static const char *prefix = PREFIX; -#endif - struct strbuf d = STRBUF_INIT; - - if (is_absolute_path(path)) - return xstrdup(path); -#ifdef RUNTIME_PREFIX assert(argv0_path); assert(is_absolute_path(argv0_path)); @@ -32,10 +25,7 @@ char *system_path(const char *path) "but prefix computation failed. " "Using static fallback '%s'.\n", prefix); } -#endif - - strbuf_addf(&d, "%s/%s", prefix, path); - return strbuf_detach(&d, NULL); + return prefix; } void git_extract_argv0_path(const char *argv0) @@ -51,6 +41,30 @@ void git_extract_argv0_path(const char *argv0) argv0_path = xstrndup(argv0, slash - argv0); } +#else + +static const char *system_prefix(void) +{ + return PREFIX; +} + +void git_extract_argv0_path(const char *argv0) +{ +} + +#endif /* RUNTIME_PREFIX */ + +char *system_path(const char *path) +{ + struct strbuf d = STRBUF_INIT; + + if (is_absolute_path(path)) + return xstrdup(path); + + strbuf_addf(&d, "%s/%s", system_prefix(), path); + return strbuf_detach(&d, NULL); +} + void git_set_argv_exec_path(const char *exec_path) { argv_exec_path = exec_path; diff --git a/git-archimport.perl b/git-archimport.perl index 9cb123a07d..b7c173c345 100755 --- a/git-archimport.perl +++ b/git-archimport.perl @@ -983,7 +983,7 @@ sub find_parents { # check that we actually know about the branch next unless -e "$git_dir/refs/heads/$branch"; - my $mergebase = `git-merge-base $branch $ps->{branch}`; + my $mergebase = safe_pipe_capture(qw(git-merge-base), $branch, $ps->{branch}); if ($?) { # Don't die here, Arch supports one-way cherry-picking # between branches with no common base (or any relationship @@ -1074,7 +1074,7 @@ sub find_parents { sub git_rev_parse { my $name = shift; - my $val = `git-rev-parse $name`; + my $val = safe_pipe_capture(qw(git-rev-parse), $name); die "Error: git-rev-parse $name" if $?; chomp $val; return $val; diff --git a/git-cvsimport.perl b/git-cvsimport.perl index 1e4e65a45d..36929921ea 100755 --- a/git-cvsimport.perl +++ b/git-cvsimport.perl @@ -642,6 +642,7 @@ sub is_sha1 { sub get_headref ($) { my $name = shift; + $name =~ s/'/'\\''/; my $r = `git rev-parse --verify '$name' 2>/dev/null`; return undef unless $? == 0; chomp $r; diff --git a/git-cvsserver.perl b/git-cvsserver.perl index d50c85ed7b..ae1044273d 100755 --- a/git-cvsserver.perl +++ b/git-cvsserver.perl @@ -356,7 +356,7 @@ sub req_Root return 0; } - my @gitvars = `git config -l`; + my @gitvars = safe_pipe_capture(qw(git config -l)); if ($?) { print "E problems executing git-config on the server -- this is not a git repository or the PATH is not set correctly.\n"; print "E \n"; @@ -841,7 +841,7 @@ sub req_Modified # Save the file data in $state $state->{entries}{$state->{directory}.$data}{modified_filename} = $filename; $state->{entries}{$state->{directory}.$data}{modified_mode} = $mode; - $state->{entries}{$state->{directory}.$data}{modified_hash} = `git hash-object $filename`; + $state->{entries}{$state->{directory}.$data}{modified_hash} = safe_pipe_capture('git','hash-object',$filename); $state->{entries}{$state->{directory}.$data}{modified_hash} =~ s/\s.*$//s; #$log->debug("req_Modified : file=$data mode=$mode size=$size"); @@ -943,7 +943,7 @@ sub req_co # Provide list of modules, if -c was used. if (exists $state->{opt}{c}) { - my $showref = `git show-ref --heads`; + my $showref = safe_pipe_capture(qw(git show-ref --heads)); for my $line (split '\n', $showref) { if ( $line =~ m% refs/heads/(.*)$% ) { print "M $1\t$1\n"; @@ -1181,7 +1181,7 @@ sub req_update # projects (heads in this case) to checkout. # if ($state->{module} eq '') { - my $showref = `git show-ref --heads`; + my $showref = safe_pipe_capture(qw(git show-ref --heads)); print "E cvs update: Updating .\n"; for my $line (split '\n', $showref) { if ( $line =~ m% refs/heads/(.*)$% ) { @@ -1463,7 +1463,7 @@ sub req_update # transmit file, format is single integer on a line by itself (file # size) followed by the file contents # TODO : we should copy files in blocks - my $data = `cat $mergedFile`; + my $data = safe_pipe_capture('cat', $mergedFile); $log->debug("File size : " . length($data)); print length($data) . "\n"; print $data; @@ -1579,7 +1579,7 @@ sub req_ci $branchRef = "refs/heads/$stickyInfo->{tag}"; } - $parenthash = `git show-ref -s $branchRef`; + $parenthash = safe_pipe_capture('git', 'show-ref', '-s', $branchRef); chomp $parenthash; if ($parenthash !~ /^[0-9a-f]{40}$/) { @@ -1687,7 +1687,7 @@ sub req_ci return; } - my $treehash = `git write-tree`; + my $treehash = safe_pipe_capture(qw(git write-tree)); chomp $treehash; $log->debug("Treehash : $treehash, Parenthash : $parenthash"); @@ -1704,7 +1704,7 @@ sub req_ci } close $msg_fh; - my $commithash = `git commit-tree $treehash -p $parenthash < $msg_filename`; + my $commithash = safe_pipe_capture('git', 'commit-tree', $treehash, '-p', $parenthash, '-F', $msg_filename); chomp($commithash); $log->info("Commit hash : $commithash"); @@ -2854,12 +2854,12 @@ sub transmitfile die "Need filehash" unless ( defined ( $filehash ) and $filehash =~ /^[a-zA-Z0-9]{40}$/ ); - my $type = `git cat-file -t $filehash`; + my $type = safe_pipe_capture('git', 'cat-file', '-t', $filehash); chomp $type; die ( "Invalid type '$type' (expected 'blob')" ) unless ( defined ( $type ) and $type eq "blob" ); - my $size = `git cat-file -s $filehash`; + my $size = safe_pipe_capture('git', 'cat-file', '-s', $filehash); chomp $size; $log->debug("transmitfile($filehash) size=$size, type=$type"); @@ -3040,7 +3040,7 @@ sub ensureWorkTree chdir $work->{emptyDir} or die "Unable to chdir to $work->{emptyDir}\n"; - my $ver = `git show-ref -s refs/heads/$state->{module}`; + my $ver = safe_pipe_capture('git', 'show-ref', '-s', "refs/heads/$state->{module}"); chomp $ver; if ($ver !~ /^[0-9a-f]{40}$/) { @@ -3287,7 +3287,7 @@ sub open_blob_or_die die "Need filehash\n"; } - my $type = `git cat-file -t $name`; + my $type = safe_pipe_capture('git', 'cat-file', '-t', $name); chomp $type; unless ( defined ( $type ) and $type eq "blob" ) @@ -3296,7 +3296,7 @@ sub open_blob_or_die die ( "Invalid type '$type' (expected 'blob')" ) } - my $size = `git cat-file -s $name`; + my $size = safe_pipe_capture('git', 'cat-file', '-s', $name); chomp $size; $log->debug("open_blob_or_die($name) size=$size, type=$type"); @@ -3406,6 +3406,22 @@ sub refHashEqual return $out; } +# an alternative to `command` that allows input to be passed as an array +# to work around shell problems with weird characters in arguments + +sub safe_pipe_capture { + + my @output; + + if (my $pid = open my $child, '-|') { + @output = (<$child>); + close $child or die join(' ',@_).": $! $?"; + } else { + exec(@_) or die "$! $?"; # exec() can fail the executable can't be found + } + return wantarray ? @output : join('',@output); +} + package GITCVS::log; @@ -3797,10 +3813,10 @@ sub update # first lets get the commit list $ENV{GIT_DIR} = $self->{git_path}; - my $commitsha1 = `git rev-parse $self->{module}`; + my $commitsha1 = ::safe_pipe_capture('git', 'rev-parse', $self->{module}); chomp $commitsha1; - my $commitinfo = `git cat-file commit $self->{module} 2>&1`; + my $commitinfo = ::safe_pipe_capture('git', 'cat-file', 'commit', $self->{module}); unless ( $commitinfo =~ /tree\s+[a-zA-Z0-9]{40}/ ) { die("Invalid module '$self->{module}'"); @@ -3882,7 +3898,7 @@ sub update # several candidate merge bases. let's assume # that the first one is the best one. my $base = eval { - safe_pipe_capture('git', 'merge-base', + ::safe_pipe_capture('git', 'merge-base', $lastpicked, $parent); }; # The two branches may not be related at all, @@ -4749,7 +4765,7 @@ sub getMetaFromCommithash return $retVal; } - my($fileHash)=safe_pipe_capture("git","rev-parse","$revCommit:$filename"); + my($fileHash) = ::safe_pipe_capture("git","rev-parse","$revCommit:$filename"); chomp $fileHash; if(!($fileHash=~/^[0-9a-f]{40}$/)) { @@ -4844,8 +4860,8 @@ sub lookupCommitRef return $commitHash; } - $commitHash=safe_pipe_capture("git","rev-parse","--verify","--quiet", - $self->unescapeRefName($ref)); + $commitHash = ::safe_pipe_capture("git","rev-parse","--verify","--quiet", + $self->unescapeRefName($ref)); $commitHash=~s/\s*$//; if(!($commitHash=~/^[0-9a-f]{40}$/)) { @@ -4854,7 +4870,7 @@ sub lookupCommitRef if( defined($commitHash) ) { - my $type=safe_pipe_capture("git","cat-file","-t",$commitHash); + my $type = ::safe_pipe_capture("git","cat-file","-t",$commitHash); if( ! ($type=~/^commit\s*$/ ) ) { $commitHash=undef; @@ -4907,7 +4923,7 @@ sub commitmessage return $message; } - my @lines = safe_pipe_capture("git", "cat-file", "commit", $commithash); + my @lines = ::safe_pipe_capture("git", "cat-file", "commit", $commithash); shift @lines while ( $lines[0] =~ /\S/ ); $message = join("",@lines); $message .= " " if ( $message =~ /\n$/ ); @@ -5056,25 +5072,6 @@ sub in_array return $retval; } -=head2 safe_pipe_capture - -an alternative to `command` that allows input to be passed as an array -to work around shell problems with weird characters in arguments - -=cut -sub safe_pipe_capture { - - my @output; - - if (my $pid = open my $child, '-|') { - @output = (<$child>); - close $child or die join(' ',@_).": $! $?"; - } else { - exec(@_) or die "$! $?"; # exec() can fail the executable can't be found - } - return wantarray ? @output : join('',@output); -} - =head2 mangle_dirname create a string from a directory name that is suitable to use as diff --git a/git-request-pull.sh b/git-request-pull.sh index eebd33276d..13c172bd94 100755 --- a/git-request-pull.sh +++ b/git-request-pull.sh @@ -128,7 +128,7 @@ git show -s --format='The following changes since commit %H: %s (%ci) -are available in the git repository at: +are available in the Git repository at: ' $merge_base && echo " $url $pretty_remote" && git show -s --format=' diff --git a/git-send-email.perl b/git-send-email.perl index fa6526986e..2208dcc213 100755 --- a/git-send-email.perl +++ b/git-send-email.perl @@ -155,7 +155,6 @@ sub format_2822_time { } my $have_email_valid = eval { require Email::Valid; 1 }; -my $have_mail_address = eval { require Mail::Address; 1 }; my $smtp; my $auth; my $num_sent = 0; @@ -490,11 +489,7 @@ my ($repoauthor, $repocommitter); ($repocommitter) = Git::ident_person(@repo, 'committer'); sub parse_address_line { - if ($have_mail_address) { - return map { $_->format } Mail::Address->parse($_[0]); - } else { - return Git::parse_mailboxes($_[0]); - } + return Git::parse_mailboxes($_[0]); } sub split_addrs { @@ -1089,6 +1084,26 @@ sub sanitize_address { } +sub strip_garbage_one_address { + my ($addr) = @_; + chomp $addr; + if ($addr =~ /^(("[^"]*"|[^"<]*)? *<[^>]*>).*/) { + # "Foo Bar" [possibly garbage here] + # Foo Bar [possibly garbage here] + return $1; + } + if ($addr =~ /^(<[^>]*>).*/) { + # [possibly garbage here] + # if garbage contains other addresses, they are ignored. + return $1; + } + if ($addr =~ /^([^"#,\s]*)/) { + # address without quoting: remove anything after the address + return $1; + } + return $addr; +} + sub sanitize_address_list { return (map { sanitize_address($_) } @_); } @@ -1590,10 +1605,12 @@ foreach my $t (@files) { # Now parse the message body while(<$fh>) { $message .= $_; - if (/^(Signed-off-by|Cc): ([^>]*>?)/i) { + if (/^(Signed-off-by|Cc): (.*)/i) { chomp; my ($what, $c) = ($1, $2); - chomp $c; + # strip garbage for the address we'll use: + $c = strip_garbage_one_address($c); + # sanitize a bit more to decide whether to suppress the address: my $sc = sanitize_address($c); if ($sc eq $sender) { next if ($suppress_cc{'self'}); diff --git a/http-push.c b/http-push.c index c91f40a610..df969609be 100644 --- a/http-push.c +++ b/http-push.c @@ -1017,7 +1017,7 @@ static int get_oid_hex_from_objpath(const char *path, struct object_id *oid) memcpy(hex, path, 2); path += 2; path++; /* skip '/' */ - memcpy(hex, path, GIT_SHA1_HEXSZ - 2); + memcpy(hex + 2, path, GIT_SHA1_HEXSZ - 2); return get_oid_hex(hex, oid); } diff --git a/mailinfo.c b/mailinfo.c index bd574cb752..70187e3eb3 100644 --- a/mailinfo.c +++ b/mailinfo.c @@ -368,11 +368,16 @@ static struct strbuf *decode_q_segment(const struct strbuf *q_seg, int rfc2047) while ((c = *in++) != 0) { if (c == '=') { - int d = *in++; + int ch, d = *in; if (d == '\n' || !d) break; /* drop trailing newline */ - strbuf_addch(out, (hexval(d) << 4) | hexval(*in++)); - continue; + ch = hex2chr(in); + if (ch >= 0) { + strbuf_addch(out, ch); + in += 2; + continue; + } + /* garbage -- fall through */ } if (rfc2047 && c == '_') /* rfc2047 4.2 (2) */ c = 0x20; diff --git a/path.c b/path.c index e50d2befcf..2fecf854fe 100644 --- a/path.c +++ b/path.c @@ -33,11 +33,10 @@ static struct strbuf *get_pathname(void) return sb; } -static char *cleanup_path(char *path) +static const char *cleanup_path(const char *path) { /* Clean it up */ - if (!memcmp(path, "./", 2)) { - path += 2; + if (skip_prefix(path, "./", &path)) { while (*path == '/') path++; } @@ -46,7 +45,7 @@ static char *cleanup_path(char *path) static void strbuf_cleanup_path(struct strbuf *sb) { - char *path = cleanup_path(sb->buf); + const char *path = cleanup_path(sb->buf); if (path > sb->buf) strbuf_remove(sb, 0, path - sb->buf); } @@ -63,7 +62,7 @@ char *mksnpath(char *buf, size_t n, const char *fmt, ...) strlcpy(buf, bad_path, n); return buf; } - return cleanup_path(buf); + return (char *)cleanup_path(buf); } static int dir_prefix(const char *buf, const char *dir) diff --git a/pkt-line.c b/pkt-line.c index 7db9119573..f364944b93 100644 --- a/pkt-line.c +++ b/pkt-line.c @@ -136,9 +136,10 @@ static void format_packet(struct strbuf *out, const char *fmt, va_list args) static int packet_write_fmt_1(int fd, int gently, const char *fmt, va_list args) { - struct strbuf buf = STRBUF_INIT; + static struct strbuf buf = STRBUF_INIT; ssize_t count; + strbuf_reset(&buf); format_packet(&buf, fmt, args); count = write_in_full(fd, buf.buf, buf.len); if (count == buf.len) diff --git a/ref-filter.c b/ref-filter.c index bc591f4f3d..f3e53d4448 100644 --- a/ref-filter.c +++ b/ref-filter.c @@ -415,8 +415,16 @@ static int parse_ref_filter_atom(const struct ref_format *format, REALLOC_ARRAY(used_atom, used_atom_cnt); used_atom[at].name = xmemdupz(atom, ep - atom); used_atom[at].type = valid_atom[i].cmp_type; - if (arg) + if (arg) { arg = used_atom[at].name + (arg - atom) + 1; + if (!*arg) { + /* + * Treat empty sub-arguments list as NULL (i.e., + * "%(atom:)" is equivalent to "%(atom)"). + */ + arg = NULL; + } + } memset(&used_atom[at].u, 0, sizeof(used_atom[at].u)); if (valid_atom[i].parser) valid_atom[i].parser(format, &used_atom[at], arg); diff --git a/refs.c b/refs.c index ea2b9f84f8..41aec6505d 100644 --- a/refs.c +++ b/refs.c @@ -921,6 +921,8 @@ int ref_transaction_update(struct ref_transaction *transaction, return -1; } + flags &= REF_TRANSACTION_UPDATE_ALLOWED_FLAGS; + flags |= (new_sha1 ? REF_HAVE_NEW : 0) | (old_sha1 ? REF_HAVE_OLD : 0); ref_transaction_add_update(transaction, refname, flags, diff --git a/refs.h b/refs.h index 6daa78eb50..4d75c207e1 100644 --- a/refs.h +++ b/refs.h @@ -354,6 +354,14 @@ int refs_pack_refs(struct ref_store *refs, unsigned int flags); #define REF_NODEREF 0x01 #define REF_FORCE_CREATE_REFLOG 0x40 +/* + * Flags that can be passed in to ref_transaction_update + */ +#define REF_TRANSACTION_UPDATE_ALLOWED_FLAGS \ + REF_ISPRUNING | \ + REF_FORCE_CREATE_REFLOG | \ + REF_NODEREF + /* * Setup reflog before using. Fill in err and return -1 on failure. */ diff --git a/sha1-lookup.c b/sha1-lookup.c index 5f069214d9..2552b7902c 100644 --- a/sha1-lookup.c +++ b/sha1-lookup.c @@ -99,219 +99,3 @@ int sha1_pos(const unsigned char *sha1, void *table, size_t nr, } while (lo < hi); return -lo-1; } - -/* - * Conventional binary search loop looks like this: - * - * unsigned lo, hi; - * do { - * unsigned mi = (lo + hi) / 2; - * int cmp = "entry pointed at by mi" minus "target"; - * if (!cmp) - * return (mi is the wanted one) - * if (cmp > 0) - * hi = mi; "mi is larger than target" - * else - * lo = mi+1; "mi is smaller than target" - * } while (lo < hi); - * - * The invariants are: - * - * - When entering the loop, lo points at a slot that is never - * above the target (it could be at the target), hi points at a - * slot that is guaranteed to be above the target (it can never - * be at the target). - * - * - We find a point 'mi' between lo and hi (mi could be the same - * as lo, but never can be as same as hi), and check if it hits - * the target. There are three cases: - * - * - if it is a hit, we are happy. - * - * - if it is strictly higher than the target, we set it to hi, - * and repeat the search. - * - * - if it is strictly lower than the target, we update lo to - * one slot after it, because we allow lo to be at the target. - * - * If the loop exits, there is no matching entry. - * - * When choosing 'mi', we do not have to take the "middle" but - * anywhere in between lo and hi, as long as lo <= mi < hi is - * satisfied. When we somehow know that the distance between the - * target and lo is much shorter than the target and hi, we could - * pick mi that is much closer to lo than the midway. - * - * Now, we can take advantage of the fact that SHA-1 is a good hash - * function, and as long as there are enough entries in the table, we - * can expect uniform distribution. An entry that begins with for - * example "deadbeef..." is much likely to appear much later than in - * the midway of the table. It can reasonably be expected to be near - * 87% (222/256) from the top of the table. - * - * However, we do not want to pick "mi" too precisely. If the entry at - * the 87% in the above example turns out to be higher than the target - * we are looking for, we would end up narrowing the search space down - * only by 13%, instead of 50% we would get if we did a simple binary - * search. So we would want to hedge our bets by being less aggressive. - * - * The table at "table" holds at least "nr" entries of "elem_size" - * bytes each. Each entry has the SHA-1 key at "key_offset". The - * table is sorted by the SHA-1 key of the entries. The caller wants - * to find the entry with "key", and knows that the entry at "lo" is - * not higher than the entry it is looking for, and that the entry at - * "hi" is higher than the entry it is looking for. - */ -int sha1_entry_pos(const void *table, - size_t elem_size, - size_t key_offset, - unsigned lo, unsigned hi, unsigned nr, - const unsigned char *key) -{ - const unsigned char *base = table; - const unsigned char *hi_key, *lo_key; - unsigned ofs_0; - static int debug_lookup = -1; - - if (debug_lookup < 0) - debug_lookup = !!getenv("GIT_DEBUG_LOOKUP"); - - if (!nr || lo >= hi) - return -1; - - if (nr == hi) - hi_key = NULL; - else - hi_key = base + elem_size * hi + key_offset; - lo_key = base + elem_size * lo + key_offset; - - ofs_0 = 0; - do { - int cmp; - unsigned ofs, mi, range; - unsigned lov, hiv, kyv; - const unsigned char *mi_key; - - range = hi - lo; - if (hi_key) { - for (ofs = ofs_0; ofs < 20; ofs++) - if (lo_key[ofs] != hi_key[ofs]) - break; - ofs_0 = ofs; - /* - * byte 0 thru (ofs-1) are the same between - * lo and hi; ofs is the first byte that is - * different. - * - * If ofs==20, then no bytes are different, - * meaning we have entries with duplicate - * keys. We know that we are in a solid run - * of this entry (because the entries are - * sorted, and our lo and hi are the same, - * there can be nothing but this single key - * in between). So we can stop the search. - * Either one of these entries is it (and - * we do not care which), or we do not have - * it. - * - * Furthermore, we know that one of our - * endpoints must be the edge of the run of - * duplicates. For example, given this - * sequence: - * - * idx 0 1 2 3 4 5 - * key A C C C C D - * - * If we are searching for "B", we might - * hit the duplicate run at lo=1, hi=3 - * (e.g., by first mi=3, then mi=0). But we - * can never have lo > 1, because B < C. - * That is, if our key is less than the - * run, we know that "lo" is the edge, but - * we can say nothing of "hi". Similarly, - * if our key is greater than the run, we - * know that "hi" is the edge, but we can - * say nothing of "lo". - * - * Therefore if we do not find it, we also - * know where it would go if it did exist: - * just on the far side of the edge that we - * know about. - */ - if (ofs == 20) { - mi = lo; - mi_key = base + elem_size * mi + key_offset; - cmp = memcmp(mi_key, key, 20); - if (!cmp) - return mi; - if (cmp < 0) - return -1 - hi; - else - return -1 - lo; - } - - hiv = hi_key[ofs_0]; - if (ofs_0 < 19) - hiv = (hiv << 8) | hi_key[ofs_0+1]; - } else { - hiv = 256; - if (ofs_0 < 19) - hiv <<= 8; - } - lov = lo_key[ofs_0]; - kyv = key[ofs_0]; - if (ofs_0 < 19) { - lov = (lov << 8) | lo_key[ofs_0+1]; - kyv = (kyv << 8) | key[ofs_0+1]; - } - assert(lov < hiv); - - if (kyv < lov) - return -1 - lo; - if (hiv < kyv) - return -1 - hi; - - /* - * Even if we know the target is much closer to 'hi' - * than 'lo', if we pick too precisely and overshoot - * (e.g. when we know 'mi' is closer to 'hi' than to - * 'lo', pick 'mi' that is higher than the target), we - * end up narrowing the search space by a smaller - * amount (i.e. the distance between 'mi' and 'hi') - * than what we would have (i.e. about half of 'lo' - * and 'hi'). Hedge our bets to pick 'mi' less - * aggressively, i.e. make 'mi' a bit closer to the - * middle than we would otherwise pick. - */ - kyv = (kyv * 6 + lov + hiv) / 8; - if (lov < hiv - 1) { - if (kyv == lov) - kyv++; - else if (kyv == hiv) - kyv--; - } - mi = (range - 1) * (kyv - lov) / (hiv - lov) + lo; - - if (debug_lookup) { - printf("lo %u hi %u rg %u mi %u ", lo, hi, range, mi); - printf("ofs %u lov %x, hiv %x, kyv %x\n", - ofs_0, lov, hiv, kyv); - } - if (!(lo <= mi && mi < hi)) - die("assertion failure lo %u mi %u hi %u %s", - lo, mi, hi, sha1_to_hex(key)); - - mi_key = base + elem_size * mi + key_offset; - cmp = memcmp(mi_key + ofs_0, key + ofs_0, 20 - ofs_0); - if (!cmp) - return mi; - if (cmp > 0) { - hi = mi; - hi_key = mi_key; - } else { - lo = mi + 1; - lo_key = mi_key + elem_size; - } - } while (lo < hi); - return -lo-1; -} diff --git a/sha1-lookup.h b/sha1-lookup.h index 20af285681..cf5314f402 100644 --- a/sha1-lookup.h +++ b/sha1-lookup.h @@ -7,10 +7,4 @@ extern int sha1_pos(const unsigned char *sha1, void *table, size_t nr, sha1_access_fn fn); - -extern int sha1_entry_pos(const void *table, - size_t elem_size, - size_t key_offset, - unsigned lo, unsigned hi, unsigned nr, - const unsigned char *key); #endif diff --git a/sha1_file.c b/sha1_file.c index 4fa4b185f3..9008d6aa7b 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -2761,7 +2761,6 @@ off_t find_pack_entry_one(const unsigned char *sha1, const uint32_t *level1_ofs = p->index_data; const unsigned char *index = p->index_data; unsigned hi, lo, stride; - static int use_lookup = -1; static int debug_lookup = -1; if (debug_lookup < 0) @@ -2791,16 +2790,6 @@ off_t find_pack_entry_one(const unsigned char *sha1, printf("%02x%02x%02x... lo %u hi %u nr %"PRIu32"\n", sha1[0], sha1[1], sha1[2], lo, hi, p->num_objects); - if (use_lookup < 0) - use_lookup = !!getenv("GIT_USE_LOOKUP"); - if (use_lookup) { - int pos = sha1_entry_pos(index, stride, 0, - lo, hi, p->num_objects, sha1); - if (pos < 0) - return 0; - return nth_packed_object_offset(p, pos); - } - while (lo < hi) { unsigned mi = (lo + hi) / 2; int cmp = hashcmp(index + mi * stride, sha1); diff --git a/shell.c b/shell.c index fe2d314593..234b2d4f16 100644 --- a/shell.c +++ b/shell.c @@ -25,19 +25,6 @@ static int do_generic_cmd(const char *me, char *arg) return execv_git_cmd(my_argv); } -static int do_cvs_cmd(const char *me, char *arg) -{ - const char *cvsserver_argv[3] = { - "cvsserver", "server", NULL - }; - - if (!arg || strcmp(arg, "server")) - die("git-cvsserver only handles server: %s", arg); - - setup_path(); - return execv_git_cmd(cvsserver_argv); -} - static int is_valid_cmd_name(const char *cmd) { /* Test command contains no . or / characters */ @@ -134,7 +121,6 @@ static struct commands { { "git-receive-pack", do_generic_cmd }, { "git-upload-pack", do_generic_cmd }, { "git-upload-archive", do_generic_cmd }, - { "cvs", do_cvs_cmd }, { NULL }, }; diff --git a/strbuf.c b/strbuf.c index 89d22e3b09..323c49ceb3 100644 --- a/strbuf.c +++ b/strbuf.c @@ -476,6 +476,7 @@ int strbuf_getwholeline(struct strbuf *sb, FILE *fp, int term) /* Translate slopbuf to NULL, as we cannot call realloc on it */ if (!sb->alloc) sb->buf = NULL; + errno = 0; r = getdelim(&sb->buf, &sb->alloc, term, fp); if (r > 0) { diff --git a/string-list.h b/string-list.h index 29bfb7ae45..79ae567cbc 100644 --- a/string-list.h +++ b/string-list.h @@ -32,8 +32,10 @@ void string_list_clear_func(struct string_list *list, string_list_clear_func_t c typedef int (*string_list_each_func_t)(struct string_list_item *, void *); int for_each_string_list(struct string_list *list, string_list_each_func_t, void *cb_data); -#define for_each_string_list_item(item,list) \ - for (item = (list)->items; item < (list)->items + (list)->nr; ++item) +#define for_each_string_list_item(item,list) \ + for (item = (list)->items; \ + item && item < (list)->items + (list)->nr; \ + ++item) /* * Apply want to each item in list, retaining only the ones for which diff --git a/sub-process.c b/sub-process.c index fcc4832c14..80571567f2 100644 --- a/sub-process.c +++ b/sub-process.c @@ -74,13 +74,12 @@ int subprocess_start(struct hashmap *hashmap, struct subprocess_entry *entry, co { int err; struct child_process *process; - const char *argv[] = { cmd, NULL }; entry->cmd = cmd; process = &entry->process; child_process_init(process); - process->argv = argv; + argv_array_push(&process->args, cmd); process->use_shell = 1; process->in = -1; process->out = -1; @@ -181,8 +180,8 @@ static int handshake_capabilities(struct child_process *process, if (supported_capabilities) *supported_capabilities |= capabilities[i].flag; } else { - warning("subprocess '%s' requested unsupported capability '%s'", - process->argv[0], p); + die("subprocess '%s' requested unsupported capability '%s'", + process->argv[0], p); } } diff --git a/t/README b/t/README index 2f95860369..4b079e4494 100644 --- a/t/README +++ b/t/README @@ -265,12 +265,12 @@ or: $ sh ./t9200-git-cvsexport-commit.sh --run='-3 21' -As noted above, the test set is built going though items left to -right, so this: +As noted above, the test set is built by going through the items +from left to right, so this: $ sh ./t9200-git-cvsexport-commit.sh --run='1-4 !3' -will run tests 1, 2, and 4. Items that comes later have higher +will run tests 1, 2, and 4. Items that come later have higher precedence. It means that this: $ sh ./t9200-git-cvsexport-commit.sh --run='!3 1-4' diff --git a/t/check-non-portable-shell.pl b/t/check-non-portable-shell.pl index b170cbc045..03dc9d2852 100755 --- a/t/check-non-portable-shell.pl +++ b/t/check-non-portable-shell.pl @@ -17,7 +17,7 @@ sub err { while (<>) { chomp; /\bsed\s+-i/ and err 'sed -i is not portable'; - /\becho\s+-n/ and err 'echo -n is not portable (please use printf)'; + /\becho\s+-[neE]/ and err 'echo with option is not portable (please use printf)'; /^\s*declare\s+/ and err 'arrays/declare not portable'; /^\s*[^#]\s*which\s/ and err 'which is not portable (please use type)'; /\btest\s+[^=]*==/ and err '"test a == b" is not portable (please use =)'; diff --git a/t/t5001-archive-attr.sh b/t/t5001-archive-attr.sh index 897f6f06d5..e9aa97117a 100755 --- a/t/t5001-archive-attr.sh +++ b/t/t5001-archive-attr.sh @@ -73,7 +73,7 @@ test_expect_missing archive-pathspec/ignored-by-tree test_expect_missing archive-pathspec/ignored-by-tree.d test_expect_missing archive-pathspec/ignored-by-tree.d/file test_expect_exists archive-pathspec/ignored-by-worktree -test_expect_missing archive-pathspec/excluded-by-pathspec.d failure +test_expect_missing archive-pathspec/excluded-by-pathspec.d test_expect_missing archive-pathspec/excluded-by-pathspec.d/file test_expect_success 'git archive with wildcard pathspec' ' diff --git a/t/t5002-archive-attr-pattern.sh b/t/t5002-archive-attr-pattern.sh index 6667d159ab..bda6d7d7e9 100755 --- a/t/t5002-archive-attr-pattern.sh +++ b/t/t5002-archive-attr-pattern.sh @@ -76,7 +76,7 @@ test_expect_missing archive/deep/and/slashless/ && test_expect_missing archive/deep/and/slashless/foo && test_expect_missing archive/deep/with/wildcard/ && test_expect_missing archive/deep/with/wildcard/foo && -test_expect_exists archive/one-level-lower/ +test_expect_missing archive/one-level-lower/ test_expect_missing archive/one-level-lower/two-levels-lower/ignored-only-if-dir/ test_expect_missing archive/one-level-lower/two-levels-lower/ignored-ony-if-dir/ignored-by-ignored-dir diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index f6207f42b5..ced44355ca 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -108,14 +108,14 @@ test_expect_success 'archive empty subtree with no pathspec' ' git archive --format=tar $root_tree >subtree-all.tar && make_dir extract && "$TAR" xf subtree-all.tar -C extract && - check_dir extract sub + check_dir extract ' test_expect_success 'archive empty subtree by direct pathspec' ' git archive --format=tar $root_tree -- sub >subtree-path.tar && make_dir extract && "$TAR" xf subtree-path.tar -C extract && - check_dir extract sub + check_dir extract ' ZIPINFO=zipinfo diff --git a/t/t5150-request-pull.sh b/t/t5150-request-pull.sh index 82c33b88e7..08c210f035 100755 --- a/t/t5150-request-pull.sh +++ b/t/t5150-request-pull.sh @@ -68,7 +68,7 @@ test_expect_success 'setup: two scripts for reading pull requests' ' cat <<-\EOT >read-request.sed && #!/bin/sed -nf # Note that a request could ask for "tag $tagname" - / in the git repository at:$/!d + / in the Git repository at:$/!d n /^$/ n s/ tag \([^ ]*\)$/ tag--\1/ @@ -192,7 +192,7 @@ test_expect_success 'pull request format' ' SUBJECT (DATE) - are available in the git repository at: + are available in the Git repository at: URL BRANCH diff --git a/t/t5308-pack-detect-duplicates.sh b/t/t5308-pack-detect-duplicates.sh index 9c5a8766ab..156ae9e9d3 100755 --- a/t/t5308-pack-detect-duplicates.sh +++ b/t/t5308-pack-detect-duplicates.sh @@ -56,20 +56,11 @@ test_expect_success 'create batch-check test vectors' ' EOF ' -test_expect_success 'lookup in duplicated pack (binary search)' ' +test_expect_success 'lookup in duplicated pack' ' git cat-file --batch-check actual && test_cmp expect actual ' -test_expect_success 'lookup in duplicated pack (GIT_USE_LOOKUP)' ' - ( - GIT_USE_LOOKUP=1 && - export GIT_USE_LOOKUP && - git cat-file --batch-check actual - ) && - test_cmp expect actual -' - test_expect_success 'index-pack can reject packs with duplicates' ' clear_packs && create_pack dups.pack 2 && diff --git a/t/t6002-rev-list-bisect.sh b/t/t6002-rev-list-bisect.sh index 534903bbd2..a661408038 100755 --- a/t/t6002-rev-list-bisect.sh +++ b/t/t6002-rev-list-bisect.sh @@ -236,17 +236,31 @@ test_sequence "--bisect" # # -test_expect_success '--bisect can default to good/bad refs' ' +test_expect_success 'set up fake --bisect refs' ' git update-ref refs/bisect/bad c3 && good=$(git rev-parse b1) && git update-ref refs/bisect/good-$good $good && good=$(git rev-parse c1) && - git update-ref refs/bisect/good-$good $good && + git update-ref refs/bisect/good-$good $good +' +test_expect_success 'rev-list --bisect can default to good/bad refs' ' # the only thing between c3 and c1 is c2 git rev-parse c2 >expect && git rev-list --bisect >actual && test_cmp expect actual ' +test_expect_success 'rev-parse --bisect can default to good/bad refs' ' + git rev-parse c3 ^b1 ^c1 >expect && + git rev-parse --bisect >actual && + + # output order depends on the refnames, which in turn depends on + # the exact sha1s. We just want to make sure we have the same set + # of lines in any order. + sort expect.sorted && + sort actual.sorted && + test_cmp expect.sorted actual.sorted +' + test_done diff --git a/t/t6120-describe.sh b/t/t6120-describe.sh index aa74eb8f0d..25110ea55d 100755 --- a/t/t6120-describe.sh +++ b/t/t6120-describe.sh @@ -182,10 +182,14 @@ check_describe "test2-lightweight-*" --tags --match="test2-*" check_describe "test2-lightweight-*" --long --tags --match="test2-*" HEAD^ -check_describe "test1-lightweight-*" --long --tags --match="test1-*" --match="test2-*" HEAD^ +check_describe "test2-lightweight-*" --long --tags --match="test1-*" --match="test2-*" HEAD^ check_describe "test2-lightweight-*" --long --tags --match="test1-*" --no-match --match="test2-*" HEAD^ +check_describe "test1-lightweight-*" --long --tags --match="test1-*" --match="test3-*" HEAD + +check_describe "test1-lightweight-*" --long --tags --match="test3-*" --match="test1-*" HEAD + test_expect_success 'name-rev with exact tags' ' echo A >expect && tag_object=$(git rev-parse refs/tags/A) && diff --git a/t/t6300-for-each-ref.sh b/t/t6300-for-each-ref.sh index 2274a4b733..edc1bd8eab 100755 --- a/t/t6300-for-each-ref.sh +++ b/t/t6300-for-each-ref.sh @@ -51,6 +51,7 @@ test_atom() { } test_atom head refname refs/heads/master +test_atom head refname: refs/heads/master test_atom head refname:short master test_atom head refname:lstrip=1 heads/master test_atom head refname:lstrip=2 master diff --git a/t/t8010-cat-file-filters.sh b/t/t8010-cat-file-filters.sh index d8242e467e..0f86c19174 100755 --- a/t/t8010-cat-file-filters.sh +++ b/t/t8010-cat-file-filters.sh @@ -51,6 +51,11 @@ test_expect_success '--path= complains without --textconv/--filters' ' grep "path.*needs.*filters" err ' +test_expect_success '--textconv/--filters complain without path' ' + test_must_fail git cat-file --textconv HEAD && + test_must_fail git cat-file --filters HEAD +' + test_expect_success 'cat-file --textconv --batch works' ' sha1=$(git rev-parse -q --verify HEAD:world.txt) && test_config diff.txt.textconv "tr A-Za-z N-ZA-Mn-za-m <" && diff --git a/t/t9001-send-email.sh b/t/t9001-send-email.sh index d1e4e8ad19..f30980895c 100755 --- a/t/t9001-send-email.sh +++ b/t/t9001-send-email.sh @@ -148,6 +148,8 @@ cat >expected-cc <<\EOF !two@example.com! !three@example.com! !four@example.com! +!five@example.com! +!six@example.com! EOF " @@ -161,6 +163,8 @@ test_expect_success $PREREQ 'cc trailer with various syntax' ' Cc: # trailing comments are ignored Cc: , one address per line Cc: "Some # Body" [ ] + Cc: five@example.com # not.six@example.com + Cc: six@example.com, not.seven@example.com EOF clean_fake_sendmail && git send-email -1 --to=recipient@example.com \ diff --git a/t/t9400-git-cvsserver-server.sh b/t/t9400-git-cvsserver-server.sh index 432c61d246..c30660d606 100755 --- a/t/t9400-git-cvsserver-server.sh +++ b/t/t9400-git-cvsserver-server.sh @@ -588,4 +588,52 @@ test_expect_success 'cvs annotate' ' test_cmp ../expect ../actual ' +#------------ +# running via git-shell +#------------ + +cd "$WORKDIR" + +test_expect_success 'create remote-cvs helper' ' + write_script remote-cvs <<-\EOF + exec git shell -c "cvs server" + EOF +' + +test_expect_success 'cvs server does not run with vanilla git-shell' ' + ( + cd cvswork && + CVS_SERVER=$WORKDIR/remote-cvs && + export CVS_SERVER && + test_must_fail cvs log merge + ) +' + +test_expect_success 'configure git shell to run cvs server' ' + mkdir "$HOME"/git-shell-commands && + + write_script "$HOME"/git-shell-commands/cvs <<-\EOF && + if ! test $# = 1 && test "$1" = "server" + then + echo >&2 "git-cvsserver only handles \"server\"" + exit 1 + fi + exec git cvsserver server + EOF + + # Should not be used, but part of the recommended setup + write_script "$HOME"/git-shell-commands/no-interactive-login <<-\EOF + echo Interactive login forbidden + EOF +' + +test_expect_success 'cvs server can run with recommended config' ' + ( + cd cvswork && + CVS_SERVER=$WORKDIR/remote-cvs && + export CVS_SERVER && + cvs log merge + ) +' + test_done diff --git a/t/test-lib.sh b/t/test-lib.sh index 51f52dcd4e..5fbd8d4a90 100644 --- a/t/test-lib.sh +++ b/t/test-lib.sh @@ -99,7 +99,6 @@ unset VISUAL EMAIL LANGUAGE COLUMNS $("$PERL_PATH" -e ' my $ok = join("|", qw( TRACE DEBUG - USE_LOOKUP TEST .*_TEST PROVE diff --git a/userdiff.c b/userdiff.c index 2c1502f719..d314667220 100644 --- a/userdiff.c +++ b/userdiff.c @@ -38,7 +38,7 @@ IPATTERN("fortran", "|//|\\*\\*|::|[/<>=]="), IPATTERN("fountain", "^((\\.[^.]|(int|ext|est|int\\.?/ext|i/e)[. ]).*)$", "[^ \t-]+"), -PATTERNS("html", "^[ \t]*(<[Hh][1-6][ \t].*>.*)$", +PATTERNS("html", "^[ \t]*(<[Hh][1-6]([ \t].*)?>.*)$", "[^<>= \t]+"), PATTERNS("java", "!^[ \t]*(catch|do|for|if|instanceof|new|return|switch|throw|while)\n"