diff options
34 files changed, 329 insertions, 128 deletions
diff --git a/Documentation/RelNotes/2.5.1.txt b/Documentation/RelNotes/2.5.1.txt index 3c468519b9..b70553308a 100644 --- a/Documentation/RelNotes/2.5.1.txt +++ b/Documentation/RelNotes/2.5.1.txt @@ -45,5 +45,21 @@ Fixes since v2.5 stable, which was a no-no. Apply a workaround to force a particular date format. + * "git clone $URL" in recent releases of Git contains a regression in + the code that invents a new repository name incorrectly based on + the $URL. This has been corrected. + (merge db2e220 jk/guess-repo-name-regression-fix later to maint). + + * Running tests with the "-x" option to make them verbose had some + unpleasant interactions with other features of the test suite. + (merge 9b5fe78 jk/test-with-x later to maint). + + * "git pull" in recent releases of Git has a regression in the code + that allows custom path to the --upload-pack=<program>. This has + been corrected. + + * pipe() emulation used in Git for Windows looked at a wrong variable + when checking for an error from an _open_osfhandle() call. + Also contains typofixes, documentation updates and trivial code clean-ups. diff --git a/Documentation/config.txt b/Documentation/config.txt index 43bb53c047..a65cdd43c2 100644 --- a/Documentation/config.txt +++ b/Documentation/config.txt @@ -1298,7 +1298,7 @@ gc.<pattern>.reflogExpire:: the refs that match the <pattern>. gc.reflogExpireUnreachable:: -gc.<ref>.reflogExpireUnreachable:: +gc.<pattern>.reflogExpireUnreachable:: 'git reflog expire' removes reflog entries older than this time and are not reachable from the current tip; defaults to 30 days. With "<pattern>" (e.g. "refs/stash") diff --git a/Documentation/git.txt b/Documentation/git.txt index 8b7e3a2d6e..5a78d77533 100644 --- a/Documentation/git.txt +++ b/Documentation/git.txt @@ -43,9 +43,10 @@ unreleased) version of Git, that is available from the 'master' branch of the `git.git` repository. Documentation for older releases are available here: -* link:v2.5.0/git.html[documentation for release 2.5] +* link:v2.5.1/git.html[documentation for release 2.5.1] * release notes for + link:RelNotes/2.5.1.txt[2.5.1], link:RelNotes/2.5.0.txt[2.5]. * link:v2.4.8/git.html[documentation for release 2.4.8] diff --git a/Documentation/pretty-formats.txt b/Documentation/pretty-formats.txt index dc865cbb27..671cebd95c 100644 --- a/Documentation/pretty-formats.txt +++ b/Documentation/pretty-formats.txt @@ -139,7 +139,9 @@ The placeholders are: - '%f': sanitized subject line, suitable for a filename - '%b': body - '%B': raw body (unwrapped subject and body) +ifndef::git-rev-list[] - '%N': commit notes +endif::git-rev-list[] - '%GG': raw verification message from GPG for a signed commit - '%G?': show "G" for a Good signature, "B" for a Bad signature, "U" for a good, untrusted signature and "N" for no signature diff --git a/Documentation/pretty-options.txt b/Documentation/pretty-options.txt index 642af6e426..8d6c5cec4c 100644 --- a/Documentation/pretty-options.txt +++ b/Documentation/pretty-options.txt @@ -42,6 +42,7 @@ people using 80-column terminals. verbatim; this means that invalid sequences in the original commit may be copied to the output. +ifndef::git-rev-list[] --notes[=<ref>]:: Show the notes (see linkgit:git-notes[1]) that annotate the commit, when showing the commit log message. This is the default @@ -73,6 +74,7 @@ being displayed. Examples: "--notes=foo" will show only notes from --[no-]standard-notes:: These options are deprecated. Use the above --notes/--no-notes options instead. +endif::git-rev-list[] --show-signature:: Check the validity of a signed commit object by passing the signature diff --git a/Documentation/rev-list-options.txt b/Documentation/rev-list-options.txt index 77ac439234..31bee069aa 100644 --- a/Documentation/rev-list-options.txt +++ b/Documentation/rev-list-options.txt @@ -58,9 +58,11 @@ endif::git-rev-list[] more than one `--grep=<pattern>`, commits whose message matches any of the given patterns are chosen (but see `--all-match`). +ifndef::git-rev-list[] + When `--show-notes` is in effect, the message from the notes is matched as if it were part of the log message. +endif::git-rev-list[] --all-match:: Limit the commits output to ones that match all given `--grep`, diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN index 5cadf44e1a..5e23aba39c 100755 --- a/GIT-VERSION-GEN +++ b/GIT-VERSION-GEN @@ -1,7 +1,7 @@ #!/bin/sh GVF=GIT-VERSION-FILE -DEF_VER=v2.5.0 +DEF_VER=v2.5.1 LF=' ' @@ -1696,10 +1696,10 @@ $(BUILT_INS): git$X ln -s $< $@ 2>/dev/null || \ cp $< $@ -common-cmds.h: generate-cmdlist.perl command-list.txt +common-cmds.h: generate-cmdlist.sh command-list.txt common-cmds.h: $(wildcard Documentation/git-*.txt) - $(QUIET_GEN)$(PERL_PATH) generate-cmdlist.perl command-list.txt > $@+ && mv $@+ $@ + $(QUIET_GEN)./generate-cmdlist.sh command-list.txt >$@+ && mv $@+ $@ SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\ $(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\ @@ -5,7 +5,8 @@ char *alias_lookup(const char *alias) char *v = NULL; struct strbuf key = STRBUF_INIT; strbuf_addf(&key, "alias.%s", alias); - git_config_get_string(key.buf, &v); + if (git_config_key_is_valid(key.buf)) + git_config_get_string(key.buf, &v); strbuf_release(&key); return v; } diff --git a/archive-zip.c b/archive-zip.c index ae3d67f9d3..9db47357b0 100644 --- a/archive-zip.c +++ b/archive-zip.c @@ -16,7 +16,9 @@ static unsigned int zip_dir_size; static unsigned int zip_offset; static unsigned int zip_dir_offset; -static unsigned int zip_dir_entries; +static uint64_t zip_dir_entries; + +static unsigned int max_creator_version; #define ZIP_DIRECTORY_MIN_SIZE (1024 * 1024) #define ZIP_STREAM (1 << 3) @@ -86,6 +88,28 @@ struct zip_extra_mtime { unsigned char _end[1]; }; +struct zip64_dir_trailer { + unsigned char magic[4]; + unsigned char record_size[8]; + unsigned char creator_version[2]; + unsigned char version[2]; + unsigned char disk[4]; + unsigned char directory_start_disk[4]; + unsigned char entries_on_this_disk[8]; + unsigned char entries[8]; + unsigned char size[8]; + unsigned char offset[8]; + unsigned char _end[1]; +}; + +struct zip64_dir_trailer_locator { + unsigned char magic[4]; + unsigned char disk[4]; + unsigned char offset[8]; + unsigned char number_of_disks[4]; + unsigned char _end[1]; +}; + /* * On ARM, padding is added at the end of the struct, so a simple * sizeof(struct ...) reports two bytes more than the payload size @@ -98,6 +122,12 @@ struct zip_extra_mtime { #define ZIP_EXTRA_MTIME_SIZE offsetof(struct zip_extra_mtime, _end) #define ZIP_EXTRA_MTIME_PAYLOAD_SIZE \ (ZIP_EXTRA_MTIME_SIZE - offsetof(struct zip_extra_mtime, flags)) +#define ZIP64_DIR_TRAILER_SIZE offsetof(struct zip64_dir_trailer, _end) +#define ZIP64_DIR_TRAILER_RECORD_SIZE \ + (ZIP64_DIR_TRAILER_SIZE - \ + offsetof(struct zip64_dir_trailer, creator_version)) +#define ZIP64_DIR_TRAILER_LOCATOR_SIZE \ + offsetof(struct zip64_dir_trailer_locator, _end) static void copy_le16(unsigned char *dest, unsigned int n) { @@ -113,6 +143,31 @@ static void copy_le32(unsigned char *dest, unsigned int n) dest[3] = 0xff & (n >> 030); } +static void copy_le64(unsigned char *dest, uint64_t n) +{ + dest[0] = 0xff & n; + dest[1] = 0xff & (n >> 010); + dest[2] = 0xff & (n >> 020); + dest[3] = 0xff & (n >> 030); + dest[4] = 0xff & (n >> 040); + dest[5] = 0xff & (n >> 050); + dest[6] = 0xff & (n >> 060); + dest[7] = 0xff & (n >> 070); +} + +static uint64_t clamp_max(uint64_t n, uint64_t max, int *clamped) +{ + if (n <= max) + return n; + *clamped = 1; + return max; +} + +static void copy_le16_clamp(unsigned char *dest, uint64_t n, int *clamped) +{ + copy_le16(dest, clamp_max(n, 0xffff, clamped)); +} + static void *zlib_deflate_raw(void *data, unsigned long size, int compression_level, unsigned long *compressed_size) @@ -223,6 +278,7 @@ static int write_zip_entry(struct archiver_args *args, unsigned long size; int is_binary = -1; const char *path_without_prefix = path + args->baselen; + unsigned int creator_version = 0; crc = crc32(0, NULL, 0); @@ -251,6 +307,8 @@ static int write_zip_entry(struct archiver_args *args, method = 0; attr2 = S_ISLNK(mode) ? ((mode | 0777) << 16) : (mode & 0111) ? ((mode) << 16) : 0; + if (S_ISLNK(mode) || (mode & 0111)) + creator_version = 0x0317; if (S_ISREG(mode) && args->compression_level != 0 && size > 0) method = 8; @@ -279,6 +337,9 @@ static int write_zip_entry(struct archiver_args *args, sha1_to_hex(sha1)); } + if (creator_version > max_creator_version) + max_creator_version = creator_version; + if (buffer && method == 8) { out = deflated = zlib_deflate_raw(buffer, size, args->compression_level, @@ -303,8 +364,7 @@ static int write_zip_entry(struct archiver_args *args, } copy_le32(dirent.magic, 0x02014b50); - copy_le16(dirent.creator_version, - S_ISLNK(mode) || (S_ISREG(mode) && (mode & 0111)) ? 0x0317 : 0); + copy_le16(dirent.creator_version, creator_version); copy_le16(dirent.version, 10); copy_le16(dirent.flags, flags); copy_le16(dirent.compression_method, method); @@ -437,20 +497,49 @@ static int write_zip_entry(struct archiver_args *args, return 0; } +static void write_zip64_trailer(void) +{ + struct zip64_dir_trailer trailer64; + struct zip64_dir_trailer_locator locator64; + + copy_le32(trailer64.magic, 0x06064b50); + copy_le64(trailer64.record_size, ZIP64_DIR_TRAILER_RECORD_SIZE); + copy_le16(trailer64.creator_version, max_creator_version); + copy_le16(trailer64.version, 45); + copy_le32(trailer64.disk, 0); + copy_le32(trailer64.directory_start_disk, 0); + copy_le64(trailer64.entries_on_this_disk, zip_dir_entries); + copy_le64(trailer64.entries, zip_dir_entries); + copy_le64(trailer64.size, zip_dir_offset); + copy_le64(trailer64.offset, zip_offset); + + copy_le32(locator64.magic, 0x07064b50); + copy_le32(locator64.disk, 0); + copy_le64(locator64.offset, zip_offset + zip_dir_offset); + copy_le32(locator64.number_of_disks, 1); + + write_or_die(1, &trailer64, ZIP64_DIR_TRAILER_SIZE); + write_or_die(1, &locator64, ZIP64_DIR_TRAILER_LOCATOR_SIZE); +} + static void write_zip_trailer(const unsigned char *sha1) { struct zip_dir_trailer trailer; + int clamped = 0; copy_le32(trailer.magic, 0x06054b50); copy_le16(trailer.disk, 0); copy_le16(trailer.directory_start_disk, 0); - copy_le16(trailer.entries_on_this_disk, zip_dir_entries); - copy_le16(trailer.entries, zip_dir_entries); + copy_le16_clamp(trailer.entries_on_this_disk, zip_dir_entries, + &clamped); + copy_le16_clamp(trailer.entries, zip_dir_entries, &clamped); copy_le32(trailer.size, zip_dir_offset); copy_le32(trailer.offset, zip_offset); copy_le16(trailer.comment_length, sha1 ? GIT_SHA1_HEXSZ : 0); write_or_die(1, zip_dir, zip_dir_offset); + if (clamped) + write_zip64_trailer(); write_or_die(1, &trailer, ZIP_DIR_TRAILER_SIZE); if (sha1) write_or_die(1, sha1_to_hex(sha1), GIT_SHA1_HEXSZ); diff --git a/builtin/checkout.c b/builtin/checkout.c index f71844a23a..3b6e499929 100644 --- a/builtin/checkout.c +++ b/builtin/checkout.c @@ -282,7 +282,7 @@ static int checkout_paths(const struct checkout_opts *opts, if (opts->source_tree) read_tree_some(opts->source_tree, &opts->pathspec); - ps_matched = xcalloc(1, opts->pathspec.nr); + ps_matched = xcalloc(opts->pathspec.nr, 1); /* * Make sure all pathspecs participated in locating the paths diff --git a/builtin/fetch.c b/builtin/fetch.c index 8d5b2dba2b..635bbdfc88 100644 --- a/builtin/fetch.c +++ b/builtin/fetch.c @@ -979,17 +979,15 @@ static int get_remote_group(const char *key, const char *value, void *priv) { struct remote_group_data *g = priv; - if (starts_with(key, "remotes.") && - !strcmp(key + 8, g->name)) { + if (skip_prefix(key, "remotes.", &key) && !strcmp(key, g->name)) { /* split list by white space */ - int space = strcspn(value, " \t\n"); while (*value) { - if (space > 1) { + size_t wordlen = strcspn(value, " \t\n"); + + if (wordlen >= 1) string_list_append(g->list, - xstrndup(value, space)); - } - value += space + (value[space] != '\0'); - space = strcspn(value, " \t\n"); + xstrndup(value, wordlen)); + value += wordlen + (value[wordlen] != '\0'); } } diff --git a/builtin/ls-files.c b/builtin/ls-files.c index 6fa2205734..b6a7cb0c7c 100644 --- a/builtin/ls-files.c +++ b/builtin/ls-files.c @@ -516,7 +516,7 @@ int cmd_ls_files(int argc, const char **argv, const char *cmd_prefix) /* Treat unmatching pathspec elements as errors */ if (pathspec.nr && error_unmatch) - ps_matched = xcalloc(1, pathspec.nr); + ps_matched = xcalloc(pathspec.nr, 1); if ((dir.flags & DIR_SHOW_IGNORED) && !exc_given) die("ls-files --ignored needs some exclude pattern"); diff --git a/builtin/rev-list.c b/builtin/rev-list.c index c0b4b53652..d80d1ed359 100644 --- a/builtin/rev-list.c +++ b/builtin/rev-list.c @@ -350,6 +350,9 @@ int cmd_rev_list(int argc, const char **argv, const char *prefix) revs.diff) usage(rev_list_usage); + if (revs.show_notes) + die(_("rev-list does not support display of notes")); + save_commit_buffer = (revs.verbose_header || revs.grep_filter.pattern_list || revs.grep_filter.header_list); @@ -1446,6 +1446,7 @@ extern int git_config_pathname(const char **, const char *, const char *); extern int git_config_set_in_file(const char *, const char *, const char *); extern int git_config_set(const char *, const char *); extern int git_config_parse_key(const char *, char **, int *); +extern int git_config_key_is_valid(const char *key); extern int git_config_set_multivar(const char *, const char *, const char *, int); extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int); extern int git_config_rename_section(const char *, const char *); diff --git a/compat/mingw.c b/compat/mingw.c index 496e6f8bb0..f74da235f5 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -681,7 +681,7 @@ int pipe(int filedes[2]) return -1; } filedes[1] = _open_osfhandle((int)h[1], O_NOINHERIT); - if (filedes[0] < 0) { + if (filedes[1] < 0) { close(filedes[0]); CloseHandle(h[1]); return -1; @@ -1848,7 +1848,7 @@ int git_config_set(const char *key, const char *value) * baselen - pointer to int which will hold the length of the * section + subsection part, can be NULL */ -int git_config_parse_key(const char *key, char **store_key, int *baselen_) +static int git_config_parse_key_1(const char *key, char **store_key, int *baselen_, int quiet) { int i, dot, baselen; const char *last_dot = strrchr(key, '.'); @@ -1859,12 +1859,14 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_) */ if (last_dot == NULL || last_dot == key) { - error("key does not contain a section: %s", key); + if (!quiet) + error("key does not contain a section: %s", key); return -CONFIG_NO_SECTION_OR_NAME; } if (!last_dot[1]) { - error("key does not contain variable name: %s", key); + if (!quiet) + error("key does not contain variable name: %s", key); return -CONFIG_NO_SECTION_OR_NAME; } @@ -1875,7 +1877,8 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_) /* * Validate the key and while at it, lower case it for matching. */ - *store_key = xmalloc(strlen(key) + 1); + if (store_key) + *store_key = xmalloc(strlen(key) + 1); dot = 0; for (i = 0; key[i]; i++) { @@ -1886,26 +1889,42 @@ int git_config_parse_key(const char *key, char **store_key, int *baselen_) if (!dot || i > baselen) { if (!iskeychar(c) || (i == baselen + 1 && !isalpha(c))) { - error("invalid key: %s", key); + if (!quiet) + error("invalid key: %s", key); goto out_free_ret_1; } c = tolower(c); } else if (c == '\n') { - error("invalid key (newline): %s", key); + if (!quiet) + error("invalid key (newline): %s", key); goto out_free_ret_1; } - (*store_key)[i] = c; + if (store_key) + (*store_key)[i] = c; } - (*store_key)[i] = 0; + if (store_key) + (*store_key)[i] = 0; return 0; out_free_ret_1: - free(*store_key); - *store_key = NULL; + if (store_key) { + free(*store_key); + *store_key = NULL; + } return -CONFIG_INVALID_KEY; } +int git_config_parse_key(const char *key, char **store_key, int *baselen) +{ + return git_config_parse_key_1(key, store_key, baselen, 0); +} + +int git_config_key_is_valid(const char *key) +{ + return !git_config_parse_key_1(key, NULL, NULL, 1); +} + /* * If value==NULL, unset in (remove from) config, * if value_regex!=NULL, disregard key/value pairs where value does not match. @@ -1935,7 +1954,7 @@ int git_config_set_multivar_in_file(const char *config_filename, const char *key, const char *value, const char *value_regex, int multi_replace) { - int fd = -1, in_fd; + int fd = -1, in_fd = -1; int ret; struct lock_file *lock = NULL; char *filename_buf = NULL; @@ -2065,6 +2084,7 @@ int git_config_set_multivar_in_file(const char *config_filename, goto out_free; } close(in_fd); + in_fd = -1; if (chmod(lock->filename.buf, st.st_mode & 07777) < 0) { error("chmod on %s failed: %s", @@ -2148,6 +2168,8 @@ out_free: free(filename_buf); if (contents) munmap(contents, contents_sz); + if (in_fd >= 0) + close(in_fd); return ret; write_err_out: diff --git a/generate-cmdlist.perl b/generate-cmdlist.perl deleted file mode 100755 index 31516e36ac..0000000000 --- a/generate-cmdlist.perl +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/perl -use strict; -use warnings; - -print <<"EOT"; -/* Automatically generated by $0 */ - -struct cmdname_help { - char name[16]; - char help[80]; - unsigned char group; -}; - -static char *common_cmd_groups[] = { -EOT - -my $n = 0; -my %grp; -while (<>) { - last if /^### command list/; - next if (1../^### common groups/) || /^#/ || /^\s*$/; - chop; - my ($k, $v) = split ' ', $_, 2; - $grp{$k} = $n++; - print "\tN_(\"$v\"),\n"; -} - -print "};\n\nstatic struct cmdname_help common_cmds[] = {\n"; - -while (<>) { - next if /^#/ || /^\s*$/; - my @tags = split; - my $cmd = shift @tags; - for my $t (@tags) { - if (exists $grp{$t}) { - my $s; - open my $f, '<', "Documentation/$cmd.txt" or die; - while (<$f>) { - ($s) = /^$cmd - (.+)$/; - last if $s; - } - close $f; - $cmd =~ s/^git-//; - print "\t{\"$cmd\", N_(\"$s\"), $grp{$t}},\n"; - last; - } - } -} - -print "};\n"; diff --git a/generate-cmdlist.sh b/generate-cmdlist.sh new file mode 100755 index 0000000000..ab0d1b0c06 --- /dev/null +++ b/generate-cmdlist.sh @@ -0,0 +1,50 @@ +#!/bin/sh + +echo "/* Automatically generated by $0 */ +struct cmdname_help { + char name[16]; + char help[80]; + unsigned char group; +}; + +static const char *common_cmd_groups[] = {" + +grps=grps$$.tmp +match=match$$.tmp +trap "rm -f '$grps' '$match'" 0 1 2 3 15 + +sed -n ' + 1,/^### common groups/b + /^### command list/q + /^#/b + /^[ ]*$/b + h;s/^[^ ][^ ]*[ ][ ]*\(.*\)/ N_("\1"),/p + g;s/^\([^ ][^ ]*\)[ ].*/\1/w '$grps' + ' "$1" +printf '};\n\n' + +n=0 +substnum= +while read grp +do + echo "^git-..*[ ]$grp" + substnum="$substnum${substnum:+;}s/[ ]$grp/$n/" + n=$(($n+1)) +done <"$grps" >"$match" + +printf 'static struct cmdname_help common_cmds[] = {\n' +grep -f "$match" "$1" | +sed 's/^git-//' | +sort | +while read cmd tags +do + tag=$(echo "$tags" | sed "$substnum; s/[^0-9]//g") + sed -n ' + /^NAME/,/git-'"$cmd"'/H + ${ + x + s/.*git-'"$cmd"' - \(.*\)/ {"'"$cmd"'", N_("\1"), '$tag'},/ + p + }' "Documentation/git-$cmd.txt" +done +echo "};" diff --git a/git-compat-util.h b/git-compat-util.h index c6d391f864..076461e8c8 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -389,7 +389,6 @@ struct strbuf; /* General helper functions */ extern void vreportf(const char *prefix, const char *err, va_list params); -extern void vwritef(int fd, const char *prefix, const char *err, va_list params); extern NORETURN void usage(const char *err); extern NORETURN void usagef(const char *err, ...) __attribute__((format (printf, 1, 2))); extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2))); @@ -425,6 +424,7 @@ static inline int const_error(void) extern void set_die_routine(NORETURN_PTR void (*routine)(const char *err, va_list params)); extern void set_error_routine(void (*routine)(const char *err, va_list params)); extern void set_die_is_recursing_routine(int (*routine)(void)); +extern void set_error_handle(FILE *); extern int starts_with(const char *str, const char *prefix); @@ -150,7 +150,8 @@ int check_pager_config(const char *cmd) struct strbuf key = STRBUF_INIT; const char *value = NULL; strbuf_addf(&key, "pager.%s", cmd); - if (!git_config_get_value(key.buf, &value)) { + if (git_config_key_is_valid(key.buf) && + !git_config_get_value(key.buf, &value)) { int b = git_config_maybe_bool(key.buf, value); if (b >= 0) want = b; @@ -10,10 +10,26 @@ coordinates our localization effort in the l10 coordinator repository: https://github.com/git-l10n/git-po/ +The two character language translation codes are defined by ISO_639-1, as +stated in the gettext(1) full manual, appendix A.1, Usual Language Codes. + + +Contributing to an existing translation +--------------------------------------- As a contributor for a language XX, you should first check TEAMS file in this directory to see whether a dedicated repository for your language XX exists. Fork the dedicated repository and start to work if it exists. +Sometime, contributors may find that the translations of their Git +distributions are quite different with the translations of the +corresponding version from Git official. This is because some Git +distributions (such as from Ubuntu, etc.) have their own l10n workflow. +For this case, wrong translations should be reported and fixed through +their workflows. + + +Creating a new language translation +----------------------------------- If you are the first contributor for the language XX, please fork this repository, prepare and/or update the translated message file po/XX.po (described later), and ask the l10n coordinator to pull your work. @@ -23,6 +39,9 @@ coordinate among yourselves and nominate the team leader for your language, so that the l10n coordinator only needs to interact with one person per language. + +Translation Process Flow +------------------------ The overall data-flow looks like this: +-------------------+ +------------------+ diff --git a/run-command.c b/run-command.c index 4d73e90fad..0d01671c1f 100644 --- a/run-command.c +++ b/run-command.c @@ -200,7 +200,6 @@ static int execv_shell_cmd(const char **argv) #endif #ifndef GIT_WINDOWS_NATIVE -static int child_err = 2; static int child_notifier = -1; static void notify_parent(void) @@ -212,17 +211,6 @@ static void notify_parent(void) */ xwrite(child_notifier, "", 1); } - -static NORETURN void die_child(const char *err, va_list params) -{ - vwritef(child_err, "fatal: ", err, params); - exit(128); -} - -static void error_child(const char *err, va_list params) -{ - vwritef(child_err, "error: ", err, params); -} #endif static inline void set_cloexec(int fd) @@ -362,11 +350,10 @@ fail_pipe: * in subsequent call paths use the parent's stderr. */ if (cmd->no_stderr || need_err) { - child_err = dup(2); + int child_err = dup(2); set_cloexec(child_err); + set_error_handle(fdopen(child_err, "w")); } - set_die_routine(die_child); - set_error_routine(error_child); close(notify_pipe[0]); set_cloexec(notify_pipe[1]); @@ -402,9 +402,9 @@ static void update_linked_gitdir(const char *gitfile, const char *gitdir) struct strbuf path = STRBUF_INIT; struct stat st; - strbuf_addf(&path, "%s/gitfile", gitdir); + strbuf_addf(&path, "%s/gitdir", gitdir); if (stat(path.buf, &st) || st.st_mtime + 24 * 3600 < time(NULL)) - write_file(path.buf, 0, "%s\n", gitfile); + write_file(path.buf, 1, "%s\n", gitfile); strbuf_release(&path); } diff --git a/sha1_file.c b/sha1_file.c index 1cee438422..f2e993e0b8 100644 --- a/sha1_file.c +++ b/sha1_file.c @@ -1461,7 +1461,10 @@ int git_open_noatime(const char *name) static int sha1_file_open_flag = O_NOATIME; for (;;) { - int fd = open(name, O_RDONLY | sha1_file_open_flag); + int fd; + + errno = 0; + fd = open(name, O_RDONLY | sha1_file_open_flag); if (fd >= 0) return fd; @@ -364,19 +364,19 @@ ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint) strbuf_grow(sb, hint ? hint : 8192); for (;;) { - ssize_t cnt; + ssize_t want = sb->alloc - sb->len - 1; + ssize_t got = read_in_full(fd, sb->buf + sb->len, want); - cnt = xread(fd, sb->buf + sb->len, sb->alloc - sb->len - 1); - if (cnt < 0) { + if (got < 0) { if (oldalloc == 0) strbuf_release(sb); else strbuf_setlen(sb, oldlen); return -1; } - if (!cnt) + sb->len += got; + if (got < want) break; - sb->len += cnt; strbuf_grow(sb, 8192); } diff --git a/t/t1509-root-worktree.sh b/t/t1509-root-worktree.sh index b6977d4b39..553a3f601b 100755 --- a/t/t1509-root-worktree.sh +++ b/t/t1509-root-worktree.sh @@ -125,7 +125,7 @@ fi ONE_SHA1=d00491fd7e5bb6fa28c517a0bb32b8b506539d4d test_expect_success 'setup' ' - rm -rf /foo + rm -rf /foo && mkdir /foo && mkdir /foo/bar && echo 1 > /foo/foome && @@ -218,7 +218,7 @@ unset GIT_WORK_TREE test_expect_success 'go to /' 'cd /' test_expect_success 'setup' ' - rm -rf /.git + rm -rf /.git && echo "Initialized empty Git repository in /.git/" > expected && git init > result && test_cmp expected result @@ -241,8 +241,8 @@ say "auto bare gitdir" # DESTROYYYYY!!!!! test_expect_success 'setup' ' - rm -rf /refs /objects /info /hooks - rm /* + rm -rf /refs /objects /info /hooks && + rm -f /expected /ls.expected /me /result && cd / && echo "Initialized empty Git repository in /" > expected && git init --bare > result && diff --git a/t/t2019-checkout-ambiguous-ref.sh b/t/t2019-checkout-ambiguous-ref.sh index 8396320d52..199b22d85e 100755 --- a/t/t2019-checkout-ambiguous-ref.sh +++ b/t/t2019-checkout-ambiguous-ref.sh @@ -69,7 +69,7 @@ test_expect_success 'wildcard ambiguation, paths win' ' ) ' -test_expect_success 'wildcard ambiguation, refs lose' ' +test_expect_success !MINGW 'wildcard ambiguation, refs lose' ' git init ambi2 && ( cd ambi2 && diff --git a/t/t3020-ls-files-error-unmatch.sh b/t/t3020-ls-files-error-unmatch.sh index ca01053bcc..124e73b8e6 100755 --- a/t/t3020-ls-files-error-unmatch.sh +++ b/t/t3020-ls-files-error-unmatch.sh @@ -22,7 +22,7 @@ test_expect_success \ 'test_must_fail git ls-files --error-unmatch foo bar-does-not-match' test_expect_success \ - 'git ls-files --error-unmatch should succeed eith matched paths.' \ + 'git ls-files --error-unmatch should succeed with matched paths.' \ 'git ls-files --error-unmatch foo bar' test_done diff --git a/t/t5004-archive-corner-cases.sh b/t/t5004-archive-corner-cases.sh index 654addaae3..cca23383c5 100755 --- a/t/t5004-archive-corner-cases.sh +++ b/t/t5004-archive-corner-cases.sh @@ -115,4 +115,44 @@ test_expect_success 'archive empty subtree by direct pathspec' ' check_dir extract sub ' +ZIPINFO=zipinfo + +test_lazy_prereq ZIPINFO ' + n=$("$ZIPINFO" "$TEST_DIRECTORY"/t5004/empty.zip | sed -n "2s/.* //p") + test "x$n" = "x0" +' + +test_expect_success ZIPINFO 'zip archive with many entries' ' + # add a directory with 256 files + mkdir 00 && + for a in 0 1 2 3 4 5 6 7 8 9 a b c d e f + do + for b in 0 1 2 3 4 5 6 7 8 9 a b c d e f + do + : >00/$a$b + done + done && + git add 00 && + git commit -m "256 files in 1 directory" && + + # duplicate it to get 65536 files in 256 directories + subtree=$(git write-tree --prefix=00/) && + for c in 0 1 2 3 4 5 6 7 8 9 a b c d e f + do + for d in 0 1 2 3 4 5 6 7 8 9 a b c d e f + do + echo "040000 tree $subtree $c$d" + done + done >tree && + tree=$(git mktree <tree) && + + # zip them + git archive -o many.zip $tree && + + # check the number of entries in the ZIP file directory + expr 65536 + 256 >expect && + "$ZIPINFO" many.zip | head -2 | sed -n "2s/.* //p" >actual && + test_cmp expect actual +' + test_done diff --git a/t/t7006-pager.sh b/t/t7006-pager.sh index 947b690fd7..6ea7ac4c41 100755 --- a/t/t7006-pager.sh +++ b/t/t7006-pager.sh @@ -447,4 +447,13 @@ test_expect_success TTY 'external command pagers override sub-commands' ' test_cmp expect actual ' +test_expect_success 'command with underscores does not complain' ' + write_script git-under_score <<-\EOF && + echo ok + EOF + git --exec-path=. under_score >actual 2>&1 && + echo ok >expect && + test_cmp expect actual +' + test_done @@ -6,23 +6,22 @@ #include "git-compat-util.h" #include "cache.h" +static FILE *error_handle; +static int tweaked_error_buffering; + void vreportf(const char *prefix, const char *err, va_list params) { - char msg[4096]; - vsnprintf(msg, sizeof(msg), err, params); - fprintf(stderr, "%s%s\n", prefix, msg); -} + FILE *fh = error_handle ? error_handle : stderr; -void vwritef(int fd, const char *prefix, const char *err, va_list params) -{ - char msg[4096]; - int len = vsnprintf(msg, sizeof(msg), err, params); - if (len > sizeof(msg)) - len = sizeof(msg); + fflush(fh); + if (!tweaked_error_buffering) { + setvbuf(fh, NULL, _IOLBF, 0); + tweaked_error_buffering = 1; + } - write_in_full(fd, prefix, strlen(prefix)); - write_in_full(fd, msg, len); - write_in_full(fd, "\n", 1); + fputs(prefix, fh); + vfprintf(fh, err, params); + fputc('\n', fh); } static NORETURN void usage_builtin(const char *err, va_list params) @@ -76,6 +75,12 @@ void set_die_is_recursing_routine(int (*routine)(void)) die_is_recursing = routine; } +void set_error_handle(FILE *fh) +{ + error_handle = fh; + tweaked_error_buffering = 0; +} + void NORETURN usagef(const char *err, ...) { va_list params; diff --git a/wt-status.c b/wt-status.c index eaed4fed32..e8c39efbcb 100644 --- a/wt-status.c +++ b/wt-status.c @@ -1,5 +1,4 @@ #include "cache.h" -#include "pathspec.h" #include "wt-status.h" #include "object.h" #include "dir.h" diff --git a/wt-status.h b/wt-status.h index e0a99f75c7..c9b3b744e9 100644 --- a/wt-status.h +++ b/wt-status.h @@ -4,6 +4,7 @@ #include <stdio.h> #include "string-list.h" #include "color.h" +#include "pathspec.h" enum color_wt_status { WT_STATUS_HEADER = 0, |