summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.mailmap1
-rw-r--r--Documentation/RelNotes/2.3.2.txt2
-rw-r--r--Documentation/RelNotes/2.3.4.txt32
-rw-r--r--Documentation/SubmittingPatches5
-rw-r--r--Documentation/config.txt127
-rw-r--r--Documentation/git-imap-send.txt3
-rw-r--r--Documentation/git.txt17
-rwxr-xr-xGIT-VERSION-GEN2
l---------RelNotes2
-rw-r--r--archive-zip.c2
-rw-r--r--builtin/clone.c11
-rw-r--r--builtin/grep.c2
-rw-r--r--builtin/index-pack.c1
-rw-r--r--builtin/pack-objects.c2
-rw-r--r--builtin/prune.c1
-rw-r--r--builtin/repack.c8
-rw-r--r--builtin/tag.c4
-rw-r--r--bulk-checkin.c1
-rw-r--r--cache.h8
-rw-r--r--connect.c114
-rw-r--r--contrib/completion/git-completion.bash10
-rw-r--r--contrib/completion/git-prompt.sh2
-rw-r--r--csum-file.c10
-rw-r--r--diff.c1
-rw-r--r--environment.c1
-rw-r--r--fast-import.c3
-rw-r--r--fetch-pack.c14
-rw-r--r--git-rebase--interactive.sh3
-rw-r--r--git.c15
-rw-r--r--http-push.c1
-rw-r--r--imap-send.c17
-rw-r--r--log-tree.c1
-rw-r--r--read-cache.c42
-rw-r--r--refs.c72
-rw-r--r--remote-curl.c1
-rw-r--r--sha1_file.c1
-rw-r--r--sha1_name.c2
-rwxr-xr-xt/t0056-git-C.sh10
-rwxr-xr-xt/t1700-split-index.sh15
-rwxr-xr-xt/t3404-rebase-interactive.sh9
-rwxr-xr-xt/t4207-log-decoration-colors.sh16
-rwxr-xr-xt/t5312-prune-corruption.sh114
-rwxr-xr-xt/t5500-fetch-pack.sh51
-rwxr-xr-xt/t5516-fetch-push.sh13
-rwxr-xr-xt/t5551-http-fetch-smart.sh11
-rwxr-xr-xt/t5601-clone.sh59
-rwxr-xr-xt/t7510-signed-commit.sh4
-rwxr-xr-xt/t9902-completion.sh19
-rwxr-xr-xt/t9903-bash-prompt.sh11
-rw-r--r--transport.c10
-rw-r--r--upload-pack.c16
-rw-r--r--zlib.c2
52 files changed, 599 insertions, 302 deletions
diff --git a/.mailmap b/.mailmap
index bb6f52ecd9..ece2951a2b 100644
--- a/.mailmap
+++ b/.mailmap
@@ -13,6 +13,7 @@ Alex Riesen <raa.lkml@gmail.com> <raa@limbo.localdomain>
Alex Riesen <raa.lkml@gmail.com> <raa@steel.home>
Alex Vandiver <alex@chmrr.net> <alexmv@MIT.EDU>
Alexander Gavrilov <angavrilov@gmail.com>
+Alexander Kuleshov <kuleshovmail@gmail.com>
Alexey Shumkin <alex.crezoff@gmail.com> <zapped@mail.ru>
Alexey Shumkin <alex.crezoff@gmail.com> <Alex.Crezoff@gmail.com>
Anders Kaseorg <andersk@MIT.EDU> <andersk@ksplice.com>
diff --git a/Documentation/RelNotes/2.3.2.txt b/Documentation/RelNotes/2.3.2.txt
index f4caf54927..93462e45c2 100644
--- a/Documentation/RelNotes/2.3.2.txt
+++ b/Documentation/RelNotes/2.3.2.txt
@@ -24,7 +24,7 @@ Fixes since v2.3.1
"curl-config --vernum", which confused our build system.
* An earlier workaround to squelch unhelpful deprecation warnings
- from the complier on Mac OSX unnecessarily set minimum required
+ from the compiler on Mac OSX unnecessarily set minimum required
version of the OS, which the user might want to raise (or lower)
for other reasons.
diff --git a/Documentation/RelNotes/2.3.4.txt b/Documentation/RelNotes/2.3.4.txt
new file mode 100644
index 0000000000..094c7b853b
--- /dev/null
+++ b/Documentation/RelNotes/2.3.4.txt
@@ -0,0 +1,32 @@
+Git v2.3.4 Release Notes
+========================
+
+Fixes since v2.3.3
+------------------
+
+ * The 'color.status.unmerged' configuration was not described.
+
+ * "git log --decorate" did not reset colors correctly around the
+ branch names.
+
+ * "git -C '' subcmd" refused to work in the current directory, unlike
+ "cd ''" which silently behaves as a no-op.
+
+ * "git imap-send" learned to optionally talk with an IMAP server via
+ libcURL; because there is no other option when Git is built with
+ NO_OPENSSL option, use that codepath by default under such
+ configuration.
+
+ * A workaround for certain build of GPG that triggered false breakage
+ in a test has been added.
+
+ * "git rebase -i" recently started to include the number of
+ commits in the insn sheet to be processed, but on a platform
+ that prepends leading whitespaces to "wc -l" output, the numbers
+ are shown with extra whitespaces that aren't necessary.
+
+ * We did not parse username followed by literal IPv6 address in SSH
+ transport URLs, e.g. ssh://user@[2001:db8::1]:22/repo.git
+ correctly.
+
+Also contains typofixes, documentation updates and trivial code clean-ups.
diff --git a/Documentation/SubmittingPatches b/Documentation/SubmittingPatches
index ef0eeb40cd..98fc4cc1d0 100644
--- a/Documentation/SubmittingPatches
+++ b/Documentation/SubmittingPatches
@@ -136,6 +136,11 @@ that is fine, but please mark it as such.
(4) Sending your patches.
+Learn to use format-patch and send-email if possible. These commands
+are optimized for the workflow of sending patches, avoiding many ways
+your existing e-mail client that is optimized for "multipart/*" mime
+type e-mails to corrupt and render your patches unusable.
+
People on the Git mailing list need to be able to read and
comment on the changes you are submitting. It is important for
a developer to be able to "quote" your changes, using standard
diff --git a/Documentation/config.txt b/Documentation/config.txt
index 5fbe9403b8..1a8ddb41c7 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -14,7 +14,8 @@ the fully qualified variable name of the variable itself is the last
dot-separated segment and the section name is everything before the last
dot. The variable names are case-insensitive, allow only alphanumeric
characters and `-`, and must start with an alphabetic character. Some
-variables may appear multiple times.
+variables may appear multiple times; we say then that the variable is
+multivalued.
Syntax
~~~~~~
@@ -25,7 +26,7 @@ blank lines are ignored.
The file consists of sections and variables. A section begins with
the name of the section in square brackets and continues until the next
-section begins. Section names are not case sensitive. Only alphanumeric
+section begins. Section names are case-insensitive. Only alphanumeric
characters, `-` and `.` are allowed in section names. Each variable
must belong to some section, which means that there must be a section
header before the first setting of a variable.
@@ -40,8 +41,8 @@ in the section header, like in the example below:
--------
Subsection names are case sensitive and can contain any characters except
-newline (doublequote `"` and backslash have to be escaped as `\"` and `\\`,
-respectively). Section headers cannot span multiple
+newline (doublequote `"` and backslash can be included by escaping them
+as `\"` and `\\`, respectively). Section headers cannot span multiple
lines. Variables may belong directly to a section or to a given subsection.
You can have `[section]` if you have `[section "subsection"]`, but you
don't need to.
@@ -53,38 +54,27 @@ restrictions as section names.
All the other lines (and the remainder of the line after the section
header) are recognized as setting variables, in the form
-'name = value'. If there is no equal sign on the line, the entire line
-is taken as 'name' and the variable is recognized as boolean "true".
+'name = value' (or just 'name', which is a short-hand to say that
+the variable is the boolean "true").
The variable names are case-insensitive, allow only alphanumeric characters
-and `-`, and must start with an alphabetic character. There can be more
-than one value for a given variable; we say then that the variable is
-multivalued.
+and `-`, and must start with an alphabetic character.
-Leading and trailing whitespace in a variable value is discarded.
-Internal whitespace within a variable value is retained verbatim.
+A line that defines a value can be continued to the next line by
+ending it with a `\`; the backquote and the end-of-line are
+stripped. Leading whitespaces after 'name =', the remainder of the
+line after the first comment character '#' or ';', and trailing
+whitespaces of the line are discarded unless they are enclosed in
+double quotes. Internal whitespaces within the value are retained
+verbatim.
-The values following the equals sign in variable assign are all either
-a string, an integer, or a boolean. Boolean values may be given as yes/no,
-1/0, true/false or on/off. Case is not significant in boolean values, when
-converting value to the canonical form using '--bool' type specifier;
-'git config' will ensure that the output is "true" or "false".
-
-String values may be entirely or partially enclosed in double quotes.
-You need to enclose variable values in double quotes if you want to
-preserve leading or trailing whitespace, or if the variable value contains
-comment characters (i.e. it contains '#' or ';').
-Double quote `"` and backslash `\` characters in variable values must
-be escaped: use `\"` for `"` and `\\` for `\`.
+Inside double quotes, double quote `"` and backslash `\` characters
+must be escaped: use `\"` for `"` and `\\` for `\`.
The following escape sequences (beside `\"` and `\\`) are recognized:
`\n` for newline character (NL), `\t` for horizontal tabulation (HT, TAB)
and `\b` for backspace (BS). Other char escape sequences (including octal
escape sequences) are invalid.
-Variable values ending in a `\` are continued on the next line in the
-customary UNIX fashion.
-
-Some variables may require a special value format.
Includes
~~~~~~~~
@@ -126,6 +116,61 @@ Example
path = foo ; expand "foo" relative to the current file
path = ~/foo ; expand "foo" in your $HOME directory
+
+Values
+~~~~~~
+
+Values of many variables are treated as a simple string, but there
+are variables that take values of specific types and there are rules
+as to how to spell them.
+
+boolean::
+
+ When a variable is said to take a boolean value, many
+ synonyms are accepted for 'true' and 'false'; these are all
+ case-insensitive.
+
+ true;; Boolean true can be spelled as `yes`, `on`, `true`,
+ or `1`. Also, a variable defined without `= <value>`
+ is taken as true.
+
+ false;; Boolean false can be spelled as `no`, `off`,
+ `false`, or `0`.
++
+When converting value to the canonical form using '--bool' type
+specifier; 'git config' will ensure that the output is "true" or
+"false" (spelled in lowercase).
+
+integer::
+ The value for many variables that specify various sizes can
+ be suffixed with `k`, `M`,... to mean "scale the number by
+ 1024", "by 1024x1024", etc.
+
+color::
+ The value for a variables that takes a color is a list of
+ colors (at most two) and attributes (at most one), separated
+ by spaces. The colors accepted are `normal`, `black`,
+ `red`, `green`, `yellow`, `blue`, `magenta`, `cyan` and
+ `white`; the attributes are `bold`, `dim`, `ul`, `blink` and
+ `reverse`. The first color given is the foreground; the
+ second is the background. The position of the attribute, if
+ any, doesn't matter. Attributes may be turned off
+ specifically by prefixing them with `no` (e.g., `noreverse`,
+ `noul`, etc).
++
+Colors (foreground and background) may also be given as numbers between
+0 and 255; these use ANSI 256-color mode (but note that not all
+terminals may support this). If your terminal supports it, you may also
+specify 24-bit RGB values as hex, like `#ff0ab3`.
++
+The attributes are meant to be reset at the beginning of each item
+in the colored output, so setting color.decorate.branch to `black`
+will paint that branch name in a plain `black`, even if the previous
+thing on the same output line (e.g. opening parenthesis before the
+list of branch names in `log --decorate` output) is set to be
+painted with `bold` or some other attribute.
+
+
Variables
~~~~~~~~~
@@ -846,20 +891,6 @@ color.branch.<slot>::
`remote` (a remote-tracking branch in refs/remotes/),
`upstream` (upstream tracking branch), `plain` (other
refs).
-+
-The value for these configuration variables is a list of colors (at most
-two) and attributes (at most one), separated by spaces. The colors
-accepted are `normal`, `black`, `red`, `green`, `yellow`, `blue`,
-`magenta`, `cyan` and `white`; the attributes are `bold`, `dim`, `ul`,
-`blink` and `reverse`. The first color given is the foreground; the
-second is the background. The position of the attribute, if any,
-doesn't matter. Attributes may be turned off specifically by prefixing
-them with `no` (e.g., `noreverse`, `noul`, etc).
-+
-Colors (foreground and background) may also be given as numbers between
-0 and 255; these use ANSI 256-color mode (but note that not all
-terminals may support this). If your terminal supports it, you may also
-specify 24-bit RGB values as hex, like `#ff0ab3`.
color.diff::
Whether to use ANSI escape sequences to add color to patches.
@@ -879,8 +910,7 @@ color.diff.<slot>::
of `plain` (context text), `meta` (metainformation), `frag`
(hunk header), 'func' (function in hunk header), `old` (removed lines),
`new` (added lines), `commit` (commit headers), or `whitespace`
- (highlighting whitespace errors). The values of these variables may be
- specified as in color.branch.<slot>.
+ (highlighting whitespace errors).
color.decorate.<slot>::
Use customized color for 'git log --decorate' output. `<slot>` is one
@@ -917,8 +947,6 @@ color.grep.<slot>::
separators between fields on a line (`:`, `-`, and `=`)
and between hunks (`--`)
--
-+
-The values of these variables may be specified as in color.branch.<slot>.
color.interactive::
When set to `always`, always use colors for interactive prompts
@@ -931,8 +959,7 @@ color.interactive.<slot>::
Use customized color for 'git add --interactive' and 'git clean
--interactive' output. `<slot>` may be `prompt`, `header`, `help`
or `error`, for four distinct types of normal output from
- interactive commands. The values of these variables may be
- specified as in color.branch.<slot>.
+ interactive commands.
color.pager::
A boolean to enable/disable colored output when the pager is in
@@ -956,10 +983,10 @@ color.status.<slot>::
`added` or `updated` (files which are added but not committed),
`changed` (files which are changed but not added in the index),
`untracked` (files which are not tracked by Git),
- `branch` (the current branch), or
+ `branch` (the current branch),
`nobranch` (the color the 'no branch' warning is shown in, defaulting
- to red). The values of these variables may be specified as in
- color.branch.<slot>.
+ to red), or
+ `unmerged` (files which have unmerged changes).
color.ui::
This variable determines the default value for variables such
diff --git a/Documentation/git-imap-send.txt b/Documentation/git-imap-send.txt
index 77aacf1309..5d1e4c80cd 100644
--- a/Documentation/git-imap-send.txt
+++ b/Documentation/git-imap-send.txt
@@ -44,7 +44,8 @@ OPTIONS
--no-curl::
Talk to the IMAP server using git's own IMAP routines instead of
- using libcurl.
+ using libcurl. Ignored if Git was built with the NO_OPENSSL option
+ set.
CONFIGURATION
diff --git a/Documentation/git.txt b/Documentation/git.txt
index af306209e9..bfa19cb50b 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.3.3/git.html[documentation for release 2.3.3]
+* link:v2.3.4/git.html[documentation for release 2.3.4]
* release notes for
+ link:RelNotes/2.3.4.txt[2.3.4],
link:RelNotes/2.3.3.txt[2.3.3],
link:RelNotes/2.3.2.txt[2.3.2],
link:RelNotes/2.3.1.txt[2.3.1],
@@ -768,7 +769,8 @@ Git so take care if using Cogito etc.
'GIT_INDEX_VERSION'::
This environment variable allows the specification of an index
version for new repositories. It won't affect existing index
- files. By default index file version [23] is used.
+ files. By default index file version 2 or 3 is used. See
+ linkgit:git-update-index[1] for more information.
'GIT_OBJECT_DIRECTORY'::
If the object storage directory is specified via this
@@ -1026,6 +1028,17 @@ GIT_ICASE_PATHSPECS::
variable when it is invoked as the top level command by the
end user, to be recorded in the body of the reflog.
+`GIT_REF_PARANOIA`::
+ If set to `1`, include broken or badly named refs when iterating
+ over lists of refs. In a normal, non-corrupted repository, this
+ does nothing. However, enabling it may help git to detect and
+ abort some operations in the presence of broken refs. Git sets
+ this variable automatically when performing destructive
+ operations like linkgit:git-prune[1]. You should not need to set
+ it yourself unless you want to be paranoid about making sure
+ an operation has touched every ref (e.g., because you are
+ cloning a repository to make a backup).
+
Discussion[[Discussion]]
------------------------
diff --git a/GIT-VERSION-GEN b/GIT-VERSION-GEN
index f92fe17065..9905751fc2 100755
--- a/GIT-VERSION-GEN
+++ b/GIT-VERSION-GEN
@@ -1,7 +1,7 @@
#!/bin/sh
GVF=GIT-VERSION-FILE
-DEF_VER=v2.3.3
+DEF_VER=v2.3.4
LF='
'
diff --git a/RelNotes b/RelNotes
index 9b1c4acd3a..f631b25aa3 120000
--- a/RelNotes
+++ b/RelNotes
@@ -1 +1 @@
-Documentation/RelNotes/2.3.3.txt \ No newline at end of file
+Documentation/RelNotes/2.3.4.txt \ No newline at end of file
diff --git a/archive-zip.c b/archive-zip.c
index 4bde019bce..1a54e1b187 100644
--- a/archive-zip.c
+++ b/archive-zip.c
@@ -120,7 +120,6 @@ static void *zlib_deflate_raw(void *data, unsigned long size,
void *buffer;
int result;
- memset(&stream, 0, sizeof(stream));
git_deflate_init_raw(&stream, compression_level);
maxsize = git_deflate_bound(&stream, size);
buffer = xmalloc(maxsize);
@@ -349,7 +348,6 @@ static int write_zip_entry(struct archiver_args *args,
size_t out_len;
unsigned char compressed[STREAM_BUFFER_SIZE * 2];
- memset(&zstream, 0, sizeof(zstream));
git_deflate_init_raw(&zstream, args->compression_level);
compressed_size = 0;
diff --git a/builtin/clone.c b/builtin/clone.c
index 316c75d0b3..2d77a2de4f 100644
--- a/builtin/clone.c
+++ b/builtin/clone.c
@@ -842,20 +842,21 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
git_dir = mkpathdup("%s/.git", dir);
}
+ atexit(remove_junk);
+ sigchain_push_common(remove_junk_on_signal);
+
if (!option_bare) {
- junk_work_tree = work_tree;
if (safe_create_leading_directories_const(work_tree) < 0)
die_errno(_("could not create leading directories of '%s'"),
work_tree);
if (!dest_exists && mkdir(work_tree, 0777))
- die_errno(_("could not create work tree dir '%s'."),
+ die_errno(_("could not create work tree dir '%s'"),
work_tree);
+ junk_work_tree = work_tree;
set_git_work_tree(work_tree);
}
- junk_git_dir = git_dir;
- atexit(remove_junk);
- sigchain_push_common(remove_junk_on_signal);
+ junk_git_dir = git_dir;
if (safe_create_leading_directories_const(git_dir) < 0)
die(_("could not create leading directories of '%s'"), git_dir);
diff --git a/builtin/grep.c b/builtin/grep.c
index e77f7cf109..fe7b9fdd93 100644
--- a/builtin/grep.c
+++ b/builtin/grep.c
@@ -885,7 +885,7 @@ int cmd_grep(int argc, const char **argv, const char *prefix)
}
}
- if (!show_in_pager)
+ if (!show_in_pager && !opt.status_only)
setup_pager();
if (!use_index && (untracked || cached))
diff --git a/builtin/index-pack.c b/builtin/index-pack.c
index 4632117671..cf654df09b 100644
--- a/builtin/index-pack.c
+++ b/builtin/index-pack.c
@@ -1204,7 +1204,6 @@ static int write_compressed(struct sha1file *f, void *in, unsigned int size)
int status;
unsigned char outbuf[4096];
- memset(&stream, 0, sizeof(stream));
git_deflate_init(&stream, zlib_compression_level);
stream.next_in = in;
stream.avail_in = size;
diff --git a/builtin/pack-objects.c b/builtin/pack-objects.c
index d8165878e1..c3a75166bd 100644
--- a/builtin/pack-objects.c
+++ b/builtin/pack-objects.c
@@ -125,7 +125,6 @@ static unsigned long do_compress(void **pptr, unsigned long size)
void *in, *out;
unsigned long maxsize;
- memset(&stream, 0, sizeof(stream));
git_deflate_init(&stream, pack_compression_level);
maxsize = git_deflate_bound(&stream, size);
@@ -153,7 +152,6 @@ static unsigned long write_large_blob_data(struct git_istream *st, struct sha1fi
unsigned char obuf[1024 * 16];
unsigned long olen = 0;
- memset(&stream, 0, sizeof(stream));
git_deflate_init(&stream, pack_compression_level);
for (;;) {
diff --git a/builtin/prune.c b/builtin/prune.c
index 04d3b12ae4..17094ad954 100644
--- a/builtin/prune.c
+++ b/builtin/prune.c
@@ -115,6 +115,7 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
expire = ULONG_MAX;
save_commit_buffer = 0;
check_replace_refs = 0;
+ ref_paranoia = 1;
init_revisions(&revs, prefix);
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);
diff --git a/builtin/repack.c b/builtin/repack.c
index 3f852f35d1..2fe1b30d71 100644
--- a/builtin/repack.c
+++ b/builtin/repack.c
@@ -228,13 +228,17 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
get_non_kept_pack_filenames(&existing_packs);
if (existing_packs.nr && delete_redundant) {
- if (unpack_unreachable)
+ if (unpack_unreachable) {
argv_array_pushf(&cmd.args,
"--unpack-unreachable=%s",
unpack_unreachable);
- else if (pack_everything & LOOSEN_UNREACHABLE)
+ argv_array_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
+ } else if (pack_everything & LOOSEN_UNREACHABLE) {
argv_array_push(&cmd.args,
"--unpack-unreachable");
+ } else {
+ argv_array_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
+ }
}
} else {
argv_array_push(&cmd.args, "--unpacked");
diff --git a/builtin/tag.c b/builtin/tag.c
index e633f4efdb..d315827cf5 100644
--- a/builtin/tag.c
+++ b/builtin/tag.c
@@ -605,13 +605,13 @@ int cmd_tag(int argc, const char **argv, const char *prefix)
OPT_STRING('u', "local-user", &keyid, N_("key-id"),
N_("use another key to sign the tag")),
OPT__FORCE(&force, N_("replace the tag if exists")),
+
+ OPT_GROUP(N_("Tag listing options")),
OPT_COLUMN(0, "column", &colopts, N_("show tag list in columns")),
{
OPTION_CALLBACK, 0, "sort", &tag_sort, N_("type"), N_("sort tags"),
PARSE_OPT_NONEG, parse_opt_sort
},
-
- OPT_GROUP(N_("Tag listing options")),
{
OPTION_CALLBACK, 0, "contains", &with_commit, N_("commit"),
N_("print only tags that contain the commit"),
diff --git a/bulk-checkin.c b/bulk-checkin.c
index 0c4b8a7cad..8d157eba45 100644
--- a/bulk-checkin.c
+++ b/bulk-checkin.c
@@ -105,7 +105,6 @@ static int stream_to_pack(struct bulk_checkin_state *state,
int write_object = (flags & HASH_WRITE_OBJECT);
off_t offset = 0;
- memset(&s, 0, sizeof(s));
git_deflate_init(&s, pack_compression_level);
hdrlen = encode_in_pack_object_header(type, size, obuf);
diff --git a/cache.h b/cache.h
index 4d02efc905..23806394eb 100644
--- a/cache.h
+++ b/cache.h
@@ -614,6 +614,14 @@ extern int protect_hfs;
extern int protect_ntfs;
/*
+ * Include broken refs in all ref iterations, which will
+ * generally choke dangerous operations rather than letting
+ * them silently proceed without taking the broken ref into
+ * account.
+ */
+extern int ref_paranoia;
+
+/*
* The character that begins a commented line in user-editable file
* that is subject to stripspace.
*/
diff --git a/connect.c b/connect.c
index d50f52ad8b..ce0e121423 100644
--- a/connect.c
+++ b/connect.c
@@ -273,28 +273,44 @@ static enum protocol get_protocol(const char *name)
die("I don't handle protocol '%s'", name);
}
+static char *host_end(char **hoststart, int removebrackets)
+{
+ char *host = *hoststart;
+ char *end;
+ char *start = strstr(host, "@[");
+ if (start)
+ start++; /* Jump over '@' */
+ else
+ start = host;
+ if (start[0] == '[') {
+ end = strchr(start + 1, ']');
+ if (end) {
+ if (removebrackets) {
+ *end = 0;
+ memmove(start, start + 1, end - start);
+ end++;
+ }
+ } else
+ end = host;
+ } else
+ end = host;
+ return end;
+}
+
#define STR_(s) # s
#define STR(s) STR_(s)
static void get_host_and_port(char **host, const char **port)
{
char *colon, *end;
-
- if (*host[0] == '[') {
- end = strchr(*host + 1, ']');
- if (end) {
- *end = 0;
- end++;
- (*host)++;
- } else
- end = *host;
- } else
- end = *host;
+ end = host_end(host, 1);
colon = strchr(end, ':');
-
if (colon) {
- *colon = 0;
- *port = colon + 1;
+ long portnr = strtol(colon + 1, &end, 10);
+ if (end != colon + 1 && *end == '\0' && 0 <= portnr && portnr < 65536) {
+ *colon = 0;
+ *port = colon + 1;
+ }
}
}
@@ -546,13 +562,16 @@ static struct child_process *git_proxy_connect(int fd[2], char *host)
return proxy;
}
-static const char *get_port_numeric(const char *p)
+static char *get_port(char *host)
{
char *end;
+ char *p = strchr(host, ':');
+
if (p) {
long port = strtol(p + 1, &end, 10);
if (end != p + 1 && *end == '\0' && 0 <= port && port < 65536) {
- return p;
+ *p = '\0';
+ return p+1;
}
}
@@ -594,14 +613,7 @@ static enum protocol parse_connect_url(const char *url_orig, char **ret_host,
* Don't do destructive transforms as protocol code does
* '[]' unwrapping in get_host_and_port()
*/
- if (host[0] == '[') {
- end = strchr(host + 1, ']');
- if (end) {
- end++;
- } else
- end = host;
- } else
- end = host;
+ end = host_end(&host, 0);
if (protocol == PROTO_LOCAL)
path = end;
@@ -662,7 +674,7 @@ struct child_process *git_connect(int fd[2], const char *url,
signal(SIGCHLD, SIG_DFL);
protocol = parse_connect_url(url, &hostandport, &path);
- if (flags & CONNECT_DIAG_URL) {
+ if ((flags & CONNECT_DIAG_URL) && (protocol != PROTO_SSH)) {
printf("Diag: url=%s\n", url ? url : "NULL");
printf("Diag: protocol=%s\n", prot_name(protocol));
printf("Diag: hostandport=%s\n", hostandport ? hostandport : "NULL");
@@ -714,28 +726,42 @@ struct child_process *git_connect(int fd[2], const char *url,
char *ssh_host = hostandport;
const char *port = NULL;
get_host_and_port(&ssh_host, &port);
- port = get_port_numeric(port);
- ssh = getenv("GIT_SSH_COMMAND");
- if (ssh) {
- conn->use_shell = 1;
- putty = 0;
- } else {
- ssh = getenv("GIT_SSH");
- if (!ssh)
- ssh = "ssh";
- putty = !!strcasestr(ssh, "plink");
- }
+ if (!port)
+ port = get_port(ssh_host);
+
+ if (flags & CONNECT_DIAG_URL) {
+ printf("Diag: url=%s\n", url ? url : "NULL");
+ printf("Diag: protocol=%s\n", prot_name(protocol));
+ printf("Diag: userandhost=%s\n", ssh_host ? ssh_host : "NULL");
+ printf("Diag: port=%s\n", port ? port : "NONE");
+ printf("Diag: path=%s\n", path ? path : "NULL");
- argv_array_push(&conn->args, ssh);
- if (putty && !strcasestr(ssh, "tortoiseplink"))
- argv_array_push(&conn->args, "-batch");
- if (port) {
- /* P is for PuTTY, p is for OpenSSH */
- argv_array_push(&conn->args, putty ? "-P" : "-p");
- argv_array_push(&conn->args, port);
+ free(hostandport);
+ free(path);
+ return NULL;
+ } else {
+ ssh = getenv("GIT_SSH_COMMAND");
+ if (ssh) {
+ conn->use_shell = 1;
+ putty = 0;
+ } else {
+ ssh = getenv("GIT_SSH");
+ if (!ssh)
+ ssh = "ssh";
+ putty = !!strcasestr(ssh, "plink");
+ }
+
+ argv_array_push(&conn->args, ssh);
+ if (putty && !strcasestr(ssh, "tortoiseplink"))
+ argv_array_push(&conn->args, "-batch");
+ if (port) {
+ /* P is for PuTTY, p is for OpenSSH */
+ argv_array_push(&conn->args, putty ? "-P" : "-p");
+ argv_array_push(&conn->args, port);
+ }
+ argv_array_push(&conn->args, ssh_host);
}
- argv_array_push(&conn->args, ssh_host);
} else {
/* remove repo-local variables from the environment */
conn->env = local_repo_env;
diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash
index 05a3aa426f..661a8294da 100644
--- a/contrib/completion/git-completion.bash
+++ b/contrib/completion/git-completion.bash
@@ -411,12 +411,9 @@ __git_refs_remotes ()
__git_remotes ()
{
- local i IFS=$'\n' d="$(__gitdir)"
+ local d="$(__gitdir)"
test -d "$d/remotes" && ls -1 "$d/remotes"
- for i in $(git --git-dir="$d" config --get-regexp 'remote\..*\.url' 2>/dev/null); do
- i="${i#remote.}"
- echo "${i/.url*/}"
- done
+ git --git-dir="$d" remote
}
__git_list_merge_strategies ()
@@ -1305,7 +1302,7 @@ _git_gitk ()
}
__git_match_ctag() {
- awk "/^${1////\\/}/ { print \$1 }" "$2"
+ awk "/^${1//\//\\/}/ { print \$1 }" "$2"
}
_git_grep ()
@@ -2014,6 +2011,7 @@ _git_config ()
color.status.changed
color.status.header
color.status.nobranch
+ color.status.unmerged
color.status.untracked
color.status.updated
color.ui
diff --git a/contrib/completion/git-prompt.sh b/contrib/completion/git-prompt.sh
index 214e859f99..f18aedc73b 100644
--- a/contrib/completion/git-prompt.sh
+++ b/contrib/completion/git-prompt.sh
@@ -487,7 +487,7 @@ __git_ps1 ()
if [ -n "${GIT_PS1_SHOWUNTRACKEDFILES-}" ] &&
[ "$(git config --bool bash.showUntrackedFiles)" != "false" ] &&
- git ls-files --others --exclude-standard --error-unmatch -- '*' >/dev/null 2>/dev/null
+ git ls-files --others --exclude-standard --error-unmatch -- ':/*' >/dev/null 2>/dev/null
then
u="%${ZSH_VERSION+%}"
fi
diff --git a/csum-file.c b/csum-file.c
index b00b215031..a172199e44 100644
--- a/csum-file.c
+++ b/csum-file.c
@@ -130,14 +130,10 @@ struct sha1file *sha1fd_check(const char *name)
sink = open("/dev/null", O_WRONLY);
if (sink < 0)
- return NULL;
+ die_errno("unable to open /dev/null");
check = open(name, O_RDONLY);
- if (check < 0) {
- int saved_errno = errno;
- close(sink);
- errno = saved_errno;
- return NULL;
- }
+ if (check < 0)
+ die_errno("unable to open '%s'", name);
f = sha1fd(sink, name);
f->check_fd = check;
return f;
diff --git a/diff.c b/diff.c
index abc32c8a7d..7500c55095 100644
--- a/diff.c
+++ b/diff.c
@@ -2093,7 +2093,6 @@ static unsigned char *deflate_it(char *data,
unsigned char *deflated;
git_zstream stream;
- memset(&stream, 0, sizeof(stream));
git_deflate_init(&stream, zlib_compression_level);
bound = git_deflate_bound(&stream, size);
deflated = xmalloc(bound);
diff --git a/environment.c b/environment.c
index 1ade5c9684..a40044c3bf 100644
--- a/environment.c
+++ b/environment.c
@@ -24,6 +24,7 @@ int is_bare_repository_cfg = -1; /* unspecified */
int log_all_ref_updates = -1; /* unspecified */
int warn_ambiguous_refs = 1;
int warn_on_object_refname_ambiguity = 1;
+int ref_paranoia = -1;
int repository_format_version;
const char *git_commit_encoding;
const char *git_log_output_encoding;
diff --git a/fast-import.c b/fast-import.c
index aac2c24f74..77fb2ff368 100644
--- a/fast-import.c
+++ b/fast-import.c
@@ -1062,7 +1062,6 @@ static int store_object(
} else
delta = NULL;
- memset(&s, 0, sizeof(s));
git_deflate_init(&s, pack_compression_level);
if (delta) {
s.next_in = delta;
@@ -1090,7 +1089,6 @@ static int store_object(
free(delta);
delta = NULL;
- memset(&s, 0, sizeof(s));
git_deflate_init(&s, pack_compression_level);
s.next_in = (void *)dat->buf;
s.avail_in = dat->len;
@@ -1190,7 +1188,6 @@ static void stream_blob(uintmax_t len, unsigned char *sha1out, uintmax_t mark)
crc32_begin(pack_file);
- memset(&s, 0, sizeof(s));
git_deflate_init(&s, pack_compression_level);
hdrlen = encode_in_pack_object_header(OBJ_BLOB, len, out_buf);
diff --git a/fetch-pack.c b/fetch-pack.c
index 655ee64256..48526aa54b 100644
--- a/fetch-pack.c
+++ b/fetch-pack.c
@@ -544,16 +544,19 @@ static void filter_refs(struct fetch_pack_args *args,
/* Append unmatched requests to the list */
if (allow_tip_sha1_in_want) {
for (i = 0; i < nr_sought; i++) {
+ unsigned char sha1[20];
+
ref = sought[i];
if (ref->matched)
continue;
- if (get_sha1_hex(ref->name, ref->old_sha1))
+ if (get_sha1_hex(ref->name, sha1) ||
+ ref->name[40] != '\0' ||
+ hashcmp(sha1, ref->old_sha1))
continue;
ref->matched = 1;
- *newtail = ref;
- ref->next = NULL;
- newtail = &ref->next;
+ *newtail = copy_ref(ref);
+ newtail = &(*newtail)->next;
}
}
*refs = newlist;
@@ -625,7 +628,6 @@ static int everything_local(struct fetch_pack_args *args,
for (retval = 1, ref = *refs; ref ; ref = ref->next) {
const unsigned char *remote = ref->old_sha1;
- unsigned char local[20];
struct object *o;
o = lookup_object(remote);
@@ -638,8 +640,6 @@ static int everything_local(struct fetch_pack_args *args,
ref->name);
continue;
}
-
- hashcpy(ref->new_sha1, local);
if (!args->verbose)
continue;
fprintf(stderr,
diff --git a/git-rebase--interactive.sh b/git-rebase--interactive.sh
index c96b9847e9..f7deeb096e 100644
--- a/git-rebase--interactive.sh
+++ b/git-rebase--interactive.sh
@@ -1030,10 +1030,11 @@ test -n "$autosquash" && rearrange_squash "$todo"
test -n "$cmd" && add_exec_commands "$todo"
todocount=$(git stripspace --strip-comments <"$todo" | wc -l)
+todocount=${todocount##* }
cat >>"$todo" <<EOF
-$comment_char Rebase $shortrevisions onto $shortonto ($todocount TODO item(s))
+$comment_char Rebase $shortrevisions onto $shortonto ($todocount command(s))
EOF
append_todo_help
git stripspace --comment-lines >>"$todo" <<\EOF
diff --git a/git.c b/git.c
index 6b5ae6a2ac..6a255839e7 100644
--- a/git.c
+++ b/git.c
@@ -204,10 +204,12 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
fprintf(stderr, "No directory given for -C.\n" );
usage(git_usage_string);
}
- if (chdir((*argv)[1]))
- die_errno("Cannot change to '%s'", (*argv)[1]);
- if (envchanged)
- *envchanged = 1;
+ if ((*argv)[1][0]) {
+ if (chdir((*argv)[1]))
+ die_errno("Cannot change to '%s'", (*argv)[1]);
+ if (envchanged)
+ *envchanged = 1;
+ }
(*argv)++;
(*argc)--;
} else {
@@ -618,6 +620,7 @@ int main(int argc, char **av)
{
const char **argv = (const char **) av;
const char *cmd;
+ int done_help = 0;
startup_info = &git_startup_info;
@@ -680,9 +683,7 @@ int main(int argc, char **av)
setup_path();
while (1) {
- static int done_help = 0;
- static int was_alias = 0;
- was_alias = run_argv(&argc, &argv);
+ int was_alias = run_argv(&argc, &argv);
if (errno != ENOENT)
break;
if (was_alias) {
diff --git a/http-push.c b/http-push.c
index 0beb7ab67f..bfb1c9605b 100644
--- a/http-push.c
+++ b/http-push.c
@@ -365,7 +365,6 @@ static void start_put(struct transfer_request *request)
hdrlen = sprintf(hdr, "%s %lu", typename(type), len) + 1;
/* Set it up */
- memset(&stream, 0, sizeof(stream));
git_deflate_init(&stream, zlib_compression_level);
size = git_deflate_bound(&stream, len + hdrlen);
strbuf_init(&request->buffer.buf, size);
diff --git a/imap-send.c b/imap-send.c
index d69887da5a..37ac4aa86a 100644
--- a/imap-send.c
+++ b/imap-send.c
@@ -34,8 +34,16 @@ typedef void *SSL;
#include "http.h"
#endif
+#if defined(USE_CURL_FOR_IMAP_SEND) && defined(NO_OPENSSL)
+/* only available option */
+#define USE_CURL_DEFAULT 1
+#else
+/* strictly opt in */
+#define USE_CURL_DEFAULT 0
+#endif
+
static int verbosity;
-static int use_curl; /* strictly opt in */
+static int use_curl = USE_CURL_DEFAULT;
static const char * const imap_send_usage[] = { "git imap-send [-v] [-q] [--[no-]curl] < <mbox>", NULL };
@@ -1504,9 +1512,14 @@ int main(int argc, char **argv)
#ifndef USE_CURL_FOR_IMAP_SEND
if (use_curl) {
- warning("--use-curl not supported in this build");
+ warning("--curl not supported in this build");
use_curl = 0;
}
+#elif defined(NO_OPENSSL)
+ if (!use_curl) {
+ warning("--no-curl not supported in this build");
+ use_curl = 1;
+ }
#endif
if (!server.port)
diff --git a/log-tree.c b/log-tree.c
index 7f0890e4ac..53bb52659b 100644
--- a/log-tree.c
+++ b/log-tree.c
@@ -195,6 +195,7 @@ void format_decorations_extended(struct strbuf *sb,
while (decoration) {
strbuf_addstr(sb, color_commit);
strbuf_addstr(sb, prefix);
+ strbuf_addstr(sb, color_reset);
strbuf_addstr(sb, decorate_get_color(use_color, decoration->type));
if (decoration->type == DECORATION_REF_TAG)
strbuf_addstr(sb, "tag: ");
diff --git a/read-cache.c b/read-cache.c
index 8d71860f69..1bf78a445f 100644
--- a/read-cache.c
+++ b/read-cache.c
@@ -1486,18 +1486,25 @@ static struct cache_entry *create_from_disk(struct ondisk_cache_entry *ondisk,
return ce;
}
-static void check_ce_order(struct cache_entry *ce, struct cache_entry *next_ce)
-{
- int name_compare = strcmp(ce->name, next_ce->name);
- if (0 < name_compare)
- die("unordered stage entries in index");
- if (!name_compare) {
- if (!ce_stage(ce))
- die("multiple stage entries for merged file '%s'",
- ce->name);
- if (ce_stage(ce) > ce_stage(next_ce))
- die("unordered stage entries for '%s'",
- ce->name);
+static void check_ce_order(struct index_state *istate)
+{
+ unsigned int i;
+
+ for (i = 1; i < istate->cache_nr; i++) {
+ struct cache_entry *ce = istate->cache[i - 1];
+ struct cache_entry *next_ce = istate->cache[i];
+ int name_compare = strcmp(ce->name, next_ce->name);
+
+ if (0 < name_compare)
+ die("unordered stage entries in index");
+ if (!name_compare) {
+ if (!ce_stage(ce))
+ die("multiple stage entries for merged file '%s'",
+ ce->name);
+ if (ce_stage(ce) > ce_stage(next_ce))
+ die("unordered stage entries for '%s'",
+ ce->name);
+ }
}
}
@@ -1562,9 +1569,6 @@ int do_read_index(struct index_state *istate, const char *path, int must_exist)
ce = create_from_disk(disk_ce, &consumed, previous_name);
set_index_entry(istate, i, ce);
- if (i > 0)
- check_ce_order(istate->cache[i - 1], ce);
-
src_offset += consumed;
}
strbuf_release(&previous_name_buf);
@@ -1608,11 +1612,10 @@ int read_index_from(struct index_state *istate, const char *path)
ret = do_read_index(istate, path, 0);
split_index = istate->split_index;
- if (!split_index)
- return ret;
-
- if (is_null_sha1(split_index->base_sha1))
+ if (!split_index || is_null_sha1(split_index->base_sha1)) {
+ check_ce_order(istate);
return ret;
+ }
if (split_index->base)
discard_index(split_index->base);
@@ -1628,6 +1631,7 @@ int read_index_from(struct index_state *istate, const char *path)
sha1_to_hex(split_index->base_sha1)),
sha1_to_hex(split_index->base->sha1));
merge_base_index(istate);
+ check_ce_order(istate);
return ret;
}
diff --git a/refs.c b/refs.c
index 9edf18b04e..3a26ad4e65 100644
--- a/refs.c
+++ b/refs.c
@@ -1907,6 +1907,11 @@ static int do_for_each_ref(struct ref_cache *refs, const char *base,
data.fn = fn;
data.cb_data = cb_data;
+ if (ref_paranoia < 0)
+ ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 0);
+ if (ref_paranoia)
+ data.flags |= DO_FOR_EACH_INCLUDE_BROKEN;
+
return do_for_each_entry(refs, base, do_one_ref, &data);
}
@@ -2591,68 +2596,10 @@ int pack_refs(unsigned int flags)
return 0;
}
-/*
- * If entry is no longer needed in packed-refs, add it to the string
- * list pointed to by cb_data. Reasons for deleting entries:
- *
- * - Entry is broken.
- * - Entry is overridden by a loose ref.
- * - Entry does not point at a valid object.
- *
- * In the first and third cases, also emit an error message because these
- * are indications of repository corruption.
- */
-static int curate_packed_ref_fn(struct ref_entry *entry, void *cb_data)
-{
- struct string_list *refs_to_delete = cb_data;
-
- if (entry->flag & REF_ISBROKEN) {
- /* This shouldn't happen to packed refs. */
- error("%s is broken!", entry->name);
- string_list_append(refs_to_delete, entry->name);
- return 0;
- }
- if (!has_sha1_file(entry->u.value.sha1)) {
- unsigned char sha1[20];
- int flags;
-
- if (read_ref_full(entry->name, 0, sha1, &flags))
- /* We should at least have found the packed ref. */
- die("Internal error");
- if ((flags & REF_ISSYMREF) || !(flags & REF_ISPACKED)) {
- /*
- * This packed reference is overridden by a
- * loose reference, so it is OK that its value
- * is no longer valid; for example, it might
- * refer to an object that has been garbage
- * collected. For this purpose we don't even
- * care whether the loose reference itself is
- * invalid, broken, symbolic, etc. Silently
- * remove the packed reference.
- */
- string_list_append(refs_to_delete, entry->name);
- return 0;
- }
- /*
- * There is no overriding loose reference, so the fact
- * that this reference doesn't refer to a valid object
- * indicates some kind of repository corruption.
- * Report the problem, then omit the reference from
- * the output.
- */
- error("%s does not point to a valid object!", entry->name);
- string_list_append(refs_to_delete, entry->name);
- return 0;
- }
-
- return 0;
-}
-
int repack_without_refs(struct string_list *refnames, struct strbuf *err)
{
struct ref_dir *packed;
- struct string_list refs_to_delete = STRING_LIST_INIT_DUP;
- struct string_list_item *refname, *ref_to_delete;
+ struct string_list_item *refname;
int ret, needs_repacking = 0, removed = 0;
assert(err);
@@ -2688,13 +2635,6 @@ int repack_without_refs(struct string_list *refnames, struct strbuf *err)
return 0;
}
- /* Remove any other accumulated cruft */
- do_for_each_entry_in_dir(packed, 0, curate_packed_ref_fn, &refs_to_delete);
- for_each_string_list_item(ref_to_delete, &refs_to_delete) {
- if (remove_entry(packed, ref_to_delete->string) == -1)
- die("internal error");
- }
-
/* Write what remains */
ret = commit_packed_refs();
if (ret)
diff --git a/remote-curl.c b/remote-curl.c
index 515ac9b411..696a5ecf05 100644
--- a/remote-curl.c
+++ b/remote-curl.c
@@ -567,7 +567,6 @@ retry:
git_zstream stream;
int ret;
- memset(&stream, 0, sizeof(stream));
git_deflate_init_gzip(&stream, Z_BEST_COMPRESSION);
gzip_size = git_deflate_bound(&stream, rpc->len);
gzip_body = xmalloc(gzip_size);
diff --git a/sha1_file.c b/sha1_file.c
index 69a60ec88b..88f06bac92 100644
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -2943,7 +2943,6 @@ static int write_loose_object(const unsigned char *sha1, char *hdr, int hdrlen,
}
/* Set it up */
- memset(&stream, 0, sizeof(stream));
git_deflate_init(&stream, zlib_compression_level);
stream.next_out = compressed;
stream.avail_out = sizeof(compressed);
diff --git a/sha1_name.c b/sha1_name.c
index 95f9f8fa1a..6d10f052b5 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -757,7 +757,7 @@ static int get_describe_name(const char *name, int len, unsigned char *sha1)
for (cp = name + len - 1; name + 2 <= cp; cp--) {
char ch = *cp;
- if (hexval(ch) & ~0377) {
+ if (!isxdigit(ch)) {
/* We must be looking at g in "SOMETHING-g"
* for it to be describe output.
*/
diff --git a/t/t0056-git-C.sh b/t/t0056-git-C.sh
index 99c037703a..2630e756da 100755
--- a/t/t0056-git-C.sh
+++ b/t/t0056-git-C.sh
@@ -14,6 +14,16 @@ test_expect_success '"git -C <path>" runs git from the directory <path>' '
test_cmp expected actual
'
+test_expect_success '"git -C <path>" with an empty <path> is a no-op' '
+ (
+ mkdir -p dir1/subdir &&
+ cd dir1/subdir &&
+ git -C "" rev-parse --show-prefix >actual &&
+ echo subdir/ >expect &&
+ test_cmp expect actual
+ )
+'
+
test_expect_success 'Multiple -C options: "-C dir1 -C dir2" is equivalent to "-C dir1/dir2"' '
test_create_repo dir1/dir2 &&
echo 1 >dir1/dir2/b.txt &&
diff --git a/t/t1700-split-index.sh b/t/t1700-split-index.sh
index 94fb473e7c..92f7298fba 100755
--- a/t/t1700-split-index.sh
+++ b/t/t1700-split-index.sh
@@ -10,9 +10,18 @@ sane_unset GIT_TEST_SPLIT_INDEX
test_expect_success 'enable split index' '
git update-index --split-index &&
test-dump-split-index .git/index >actual &&
+ indexversion=$(test-index-version <.git/index) &&
+ if test "$indexversion" = "4"
+ then
+ own=432ef4b63f32193984f339431fd50ca796493569
+ base=508851a7f0dfa8691e9f69c7f055865389012491
+ else
+ own=8299b0bcd1ac364e5f1d7768efb62fa2da79a339
+ base=39d890139ee5356c7ef572216cebcd27aa41f9df
+ fi &&
cat >expect <<EOF &&
-own 8299b0bcd1ac364e5f1d7768efb62fa2da79a339
-base 39d890139ee5356c7ef572216cebcd27aa41f9df
+own $own
+base $base
replacements:
deletions:
EOF
@@ -30,7 +39,7 @@ EOF
test-dump-split-index .git/index | sed "/^own/d" >actual &&
cat >expect <<EOF &&
-base 39d890139ee5356c7ef572216cebcd27aa41f9df
+base $base
100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 one
replacements:
deletions:
diff --git a/t/t3404-rebase-interactive.sh b/t/t3404-rebase-interactive.sh
index a31f7e0430..034eb35cdf 100755
--- a/t/t3404-rebase-interactive.sh
+++ b/t/t3404-rebase-interactive.sh
@@ -1046,4 +1046,13 @@ test_expect_success 'respect core.abbrev' '
test 4 = $(grep -c "pick [0-9a-f]\{12,\}" todo-list)
'
+test_expect_success 'todo count' '
+ write_script dump-raw.sh <<-\EOF &&
+ cat "$1"
+ EOF
+ test_set_editor "$(pwd)/dump-raw.sh" &&
+ git rebase -i HEAD~4 >actual &&
+ grep "^# Rebase ..* onto ..* ([0-9]" actual
+'
+
test_done
diff --git a/t/t4207-log-decoration-colors.sh b/t/t4207-log-decoration-colors.sh
index 925f577a3c..6b8ad4f5b0 100755
--- a/t/t4207-log-decoration-colors.sh
+++ b/t/t4207-log-decoration-colors.sh
@@ -44,15 +44,15 @@ test_expect_success setup '
'
cat >expected <<EOF
-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_HEAD}HEAD${c_reset}${c_commit},\
- ${c_tag}tag: v1.0${c_reset}${c_commit},\
- ${c_tag}tag: B${c_reset}${c_commit},\
- ${c_branch}master${c_reset}${c_commit})${c_reset} B
-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_tag}tag: A1${c_reset}${c_commit},\
- ${c_remoteBranch}other/master${c_reset}${c_commit})${c_reset} A1
-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_HEAD}HEAD${c_reset}${c_commit},\
+ ${c_reset}${c_tag}tag: v1.0${c_reset}${c_commit},\
+ ${c_reset}${c_tag}tag: B${c_reset}${c_commit},\
+ ${c_reset}${c_branch}master${c_reset}${c_commit})${c_reset} B
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A1${c_reset}${c_commit},\
+ ${c_reset}${c_remoteBranch}other/master${c_reset}${c_commit})${c_reset} A1
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_stash}refs/stash${c_reset}${c_commit})${c_reset}\
On master: Changes to A.t
-${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
+${c_commit}COMMIT_ID${c_reset}${c_commit} (${c_reset}${c_tag}tag: A${c_reset}${c_commit})${c_reset} A
EOF
# We want log to show all, but the second parent to refs/stash is irrelevant
diff --git a/t/t5312-prune-corruption.sh b/t/t5312-prune-corruption.sh
new file mode 100755
index 0000000000..8e98b44083
--- /dev/null
+++ b/t/t5312-prune-corruption.sh
@@ -0,0 +1,114 @@
+#!/bin/sh
+
+test_description='
+Test pruning of repositories with minor corruptions. The goal
+here is that we should always be erring on the side of safety. So
+if we see, for example, a ref with a bogus name, it is OK either to
+bail out or to proceed using it as a reachable tip, but it is _not_
+OK to proceed as if it did not exist. Otherwise we might silently
+delete objects that cannot be recovered.
+'
+. ./test-lib.sh
+
+test_expect_success 'disable reflogs' '
+ git config core.logallrefupdates false &&
+ rm -rf .git/logs
+'
+
+test_expect_success 'create history reachable only from a bogus-named ref' '
+ test_tick && git commit --allow-empty -m master &&
+ base=$(git rev-parse HEAD) &&
+ test_tick && git commit --allow-empty -m bogus &&
+ bogus=$(git rev-parse HEAD) &&
+ git cat-file commit $bogus >saved &&
+ echo $bogus >.git/refs/heads/bogus..name &&
+ git reset --hard HEAD^
+'
+
+test_expect_success 'pruning does not drop bogus object' '
+ test_when_finished "git hash-object -w -t commit saved" &&
+ test_might_fail git prune --expire=now &&
+ verbose git cat-file -e $bogus
+'
+
+test_expect_success 'put bogus object into pack' '
+ git tag reachable $bogus &&
+ git repack -ad &&
+ git tag -d reachable &&
+ verbose git cat-file -e $bogus
+'
+
+test_expect_success 'destructive repack keeps packed object' '
+ test_might_fail git repack -Ad --unpack-unreachable=now &&
+ verbose git cat-file -e $bogus &&
+ test_might_fail git repack -ad &&
+ verbose git cat-file -e $bogus
+'
+
+# subsequent tests will have different corruptions
+test_expect_success 'clean up bogus ref' '
+ rm .git/refs/heads/bogus..name
+'
+
+# We create two new objects here, "one" and "two". Our
+# master branch points to "two", which is deleted,
+# corrupting the repository. But we'd like to make sure
+# that the otherwise unreachable "one" is not pruned
+# (since it is the user's best bet for recovering
+# from the corruption).
+#
+# Note that we also point HEAD somewhere besides "two",
+# as we want to make sure we test the case where we
+# pick up the reference to "two" by iterating the refs,
+# not by resolving HEAD.
+test_expect_success 'create history with missing tip commit' '
+ test_tick && git commit --allow-empty -m one &&
+ recoverable=$(git rev-parse HEAD) &&
+ git cat-file commit $recoverable >saved &&
+ test_tick && git commit --allow-empty -m two &&
+ missing=$(git rev-parse HEAD) &&
+ git checkout --detach $base &&
+ rm .git/objects/$(echo $missing | sed "s,..,&/,") &&
+ test_must_fail git cat-file -e $missing
+'
+
+test_expect_success 'pruning with a corrupted tip does not drop history' '
+ test_when_finished "git hash-object -w -t commit saved" &&
+ test_might_fail git prune --expire=now &&
+ verbose git cat-file -e $recoverable
+'
+
+test_expect_success 'pack-refs does not silently delete broken loose ref' '
+ git pack-refs --all --prune &&
+ echo $missing >expect &&
+ git rev-parse refs/heads/master >actual &&
+ test_cmp expect actual
+'
+
+# we do not want to count on running pack-refs to
+# actually pack it, as it is perfectly reasonable to
+# skip processing a broken ref
+test_expect_success 'create packed-refs file with broken ref' '
+ rm -f .git/refs/heads/master &&
+ cat >.git/packed-refs <<-EOF &&
+ $missing refs/heads/master
+ $recoverable refs/heads/other
+ EOF
+ echo $missing >expect &&
+ git rev-parse refs/heads/master >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'pack-refs does not silently delete broken packed ref' '
+ git pack-refs --all --prune &&
+ git rev-parse refs/heads/master >actual &&
+ test_cmp expect actual
+'
+
+test_expect_success 'pack-refs does not drop broken refs during deletion' '
+ git update-ref -d refs/heads/other &&
+ git rev-parse refs/heads/master >actual &&
+ test_cmp expect actual
+'
+
+test_done
diff --git a/t/t5500-fetch-pack.sh b/t/t5500-fetch-pack.sh
index 5b2b1c2c13..bd37f040b6 100755
--- a/t/t5500-fetch-pack.sh
+++ b/t/t5500-fetch-pack.sh
@@ -541,13 +541,30 @@ check_prot_path () {
test_cmp expected actual
}
-check_prot_host_path () {
- cat >expected <<-EOF &&
+check_prot_host_port_path () {
+ local diagport
+ case "$2" in
+ *ssh*)
+ pp=ssh
+ uah=userandhost
+ ehost=$(echo $3 | tr -d "[]")
+ diagport="Diag: port=$4"
+ ;;
+ *)
+ pp=$p
+ uah=hostandport
+ ehost=$(echo $3$4 | sed -e "s/22$/:22/" -e "s/NONE//")
+ diagport=""
+ ;;
+ esac
+ cat >exp <<-EOF &&
Diag: url=$1
- Diag: protocol=$2
- Diag: hostandport=$3
- Diag: path=$4
+ Diag: protocol=$pp
+ Diag: $uah=$ehost
+ $diagport
+ Diag: path=$5
EOF
+ grep -v "^$" exp >expected
git fetch-pack --diag-url "$1" >actual &&
test_cmp expected actual
}
@@ -557,22 +574,20 @@ do
# git or ssh with scheme
for p in "ssh+git" "git+ssh" git ssh
do
- for h in host host:12 [::1] [::1]:23
+ for h in host user@host user@[::1] user@::1
do
- case "$p" in
- *ssh*)
- pp=ssh
- ;;
- *)
- pp=$p
- ;;
- esac
test_expect_success "fetch-pack --diag-url $p://$h/$r" '
- check_prot_host_path $p://$h/$r $pp "$h" "/$r"
+ check_prot_host_port_path $p://$h/$r $p "$h" NONE "/$r"
'
# "/~" -> "~" conversion
test_expect_success "fetch-pack --diag-url $p://$h/~$r" '
- check_prot_host_path $p://$h/~$r $pp "$h" "~$r"
+ check_prot_host_port_path $p://$h/~$r $p "$h" NONE "~$r"
+ '
+ done
+ for h in host User@host User@[::1]
+ do
+ test_expect_success "fetch-pack --diag-url $p://$h:22/$r" '
+ check_prot_host_port_path $p://$h:22/$r $p "$h" 22 "/$r"
'
done
done
@@ -603,11 +618,11 @@ do
for h in host [::1]
do
test_expect_success "fetch-pack --diag-url $h:$r" '
- check_prot_path $h:$r $p "$r"
+ check_prot_host_port_path $h:$r $p "$h" NONE "$r"
'
# Do "/~" -> "~" conversion
test_expect_success "fetch-pack --diag-url $h:/~$r" '
- check_prot_host_path $h:/~$r $p "$h" "~$r"
+ check_prot_host_port_path $h:/~$r $p "$h" NONE "~$r"
'
done
done
diff --git a/t/t5516-fetch-push.sh b/t/t5516-fetch-push.sh
index 594d7a6998..050877f181 100755
--- a/t/t5516-fetch-push.sh
+++ b/t/t5516-fetch-push.sh
@@ -1107,9 +1107,16 @@ test_expect_success 'fetch exact SHA1' '
git config uploadpack.allowtipsha1inwant true
) &&
- git fetch -v ../testrepo $the_commit:refs/heads/copy &&
- result=$(git rev-parse --verify refs/heads/copy) &&
- test "$the_commit" = "$result"
+ git fetch -v ../testrepo $the_commit:refs/heads/copy master:refs/heads/extra &&
+ cat >expect <<-EOF &&
+ $the_commit
+ $the_first_commit
+ EOF
+ {
+ git rev-parse --verify refs/heads/copy &&
+ git rev-parse --verify refs/heads/extra
+ } >actual &&
+ test_cmp expect actual
)
'
diff --git a/t/t5551-http-fetch-smart.sh b/t/t5551-http-fetch-smart.sh
index 6cbc12d9a7..b97077351d 100755
--- a/t/t5551-http-fetch-smart.sh
+++ b/t/t5551-http-fetch-smart.sh
@@ -213,6 +213,17 @@ test_expect_success 'cookies stored in http.cookiefile when http.savecookies set
test_cmp expect_cookies.txt cookies_tail.txt
'
+test_expect_success 'transfer.hiderefs works over smart-http' '
+ test_commit hidden &&
+ test_commit visible &&
+ git push public HEAD^:refs/heads/a HEAD:refs/heads/b &&
+ git --git-dir="$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
+ config transfer.hiderefs refs/heads/a &&
+ git clone --bare "$HTTPD_URL/smart/repo.git" hidden.git &&
+ test_must_fail git -C hidden.git rev-parse --verify a &&
+ git -C hidden.git rev-parse --verify b
+'
+
test_expect_success EXPENSIVE 'create 50,000 tags in the repo' '
(
cd "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" &&
diff --git a/t/t5601-clone.sh b/t/t5601-clone.sh
index e4f10c0f68..02b40b117f 100755
--- a/t/t5601-clone.sh
+++ b/t/t5601-clone.sh
@@ -301,11 +301,17 @@ expect_ssh () {
(cd "$TRASH_DIRECTORY" && rm -f ssh-expect && >ssh-output)
' &&
{
- case "$1" in
- none)
+ case "$#" in
+ 1)
;;
- *)
+ 2)
echo "ssh: $1 git-upload-pack '$2'"
+ ;;
+ 3)
+ echo "ssh: $1 $2 git-upload-pack '$3'"
+ ;;
+ *)
+ echo "ssh: $1 $2 git-upload-pack '$3' $4"
esac
} >"$TRASH_DIRECTORY/ssh-expect" &&
(cd "$TRASH_DIRECTORY" && test_cmp ssh-expect ssh-output)
@@ -326,7 +332,7 @@ test_expect_success !MINGW,!CYGWIN 'clone local path foo:bar' '
test_expect_success 'bracketed hostnames are still ssh' '
git clone "[myhost:123]:src" ssh-bracket-clone &&
- expect_ssh myhost:123 src
+ expect_ssh myhost '-p 123' src
'
counter=0
@@ -336,7 +342,8 @@ counter=0
test_clone_url () {
counter=$(($counter + 1))
test_might_fail git clone "$1" tmp$counter &&
- expect_ssh "$2" "$3"
+ shift &&
+ expect_ssh "$@"
}
test_expect_success !MINGW 'clone c:temp is ssl' '
@@ -359,7 +366,7 @@ done
for repo in rep rep/home/project 123
do
test_expect_success "clone [::1]:$repo" '
- test_clone_url [::1]:$repo ::1 $repo
+ test_clone_url [::1]:$repo ::1 "$repo"
'
done
#home directory
@@ -400,24 +407,40 @@ test_expect_success 'clone ssh://host.xz:22/~repo' '
'
#IPv6
-test_expect_success 'clone ssh://[::1]/home/user/repo' '
- test_clone_url "ssh://[::1]/home/user/repo" "::1" "/home/user/repo"
-'
+for tuah in ::1 [::1] user@::1 user@[::1] [user@::1]
+do
+ ehost=$(echo $tuah | tr -d "[]")
+ test_expect_success "clone ssh://$tuah/home/user/repo" "
+ test_clone_url ssh://$tuah/home/user/repo $ehost /home/user/repo
+ "
+done
#IPv6 from home directory
-test_expect_success 'clone ssh://[::1]/~repo' '
- test_clone_url "ssh://[::1]/~repo" "::1" "~repo"
-'
+for tuah in ::1 [::1] user@::1 user@[::1] [user@::1]
+do
+ euah=$(echo $tuah | tr -d "[]")
+ test_expect_success "clone ssh://$tuah/~repo" "
+ test_clone_url ssh://$tuah/~repo $euah '~repo'
+ "
+done
#IPv6 with port number
-test_expect_success 'clone ssh://[::1]:22/home/user/repo' '
- test_clone_url "ssh://[::1]:22/home/user/repo" "-p 22 ::1" "/home/user/repo"
-'
+for tuah in [::1] user@[::1] [user@::1]
+do
+ euah=$(echo $tuah | tr -d "[]")
+ test_expect_success "clone ssh://$tuah:22/home/user/repo" "
+ test_clone_url ssh://$tuah:22/home/user/repo '-p 22' $euah /home/user/repo
+ "
+done
#IPv6 from home directory with port number
-test_expect_success 'clone ssh://[::1]:22/~repo' '
- test_clone_url "ssh://[::1]:22/~repo" "-p 22 ::1" "~repo"
-'
+for tuah in [::1] user@[::1] [user@::1]
+do
+ euah=$(echo $tuah | tr -d "[]")
+ test_expect_success "clone ssh://$tuah:22/~repo" "
+ test_clone_url ssh://$tuah:22/~repo '-p 22' $euah '~repo'
+ "
+done
test_expect_success 'clone from a repository with two identical branches' '
diff --git a/t/t7510-signed-commit.sh b/t/t7510-signed-commit.sh
index 474dab381a..3cef18cfda 100755
--- a/t/t7510-signed-commit.sh
+++ b/t/t7510-signed-commit.sh
@@ -86,8 +86,8 @@ test_expect_success GPG 'show signed commit with signature' '
git show -s --show-signature initial >show &&
git verify-commit -v initial >verify.1 2>verify.2 &&
git cat-file commit initial >cat &&
- grep -v "gpg: " show >show.commit &&
- grep "gpg: " show >show.gpg &&
+ grep -v -e "gpg: " -e "Warning: " show >show.commit &&
+ grep -e "gpg: " -e "Warning: " show >show.gpg &&
grep -v "^ " cat | grep -v "^gpgsig " >cat.commit &&
test_cmp show.commit commit &&
test_cmp show.gpg verify.2 &&
diff --git a/t/t9902-completion.sh b/t/t9902-completion.sh
index f10a75290e..7a883d1a67 100755
--- a/t/t9902-completion.sh
+++ b/t/t9902-completion.sh
@@ -351,6 +351,25 @@ test_expect_success '__gitcomp_nl - doesnt fail because of invalid variable name
__gitcomp_nl "$invalid_variable_name"
'
+test_expect_success '__git_remotes - list remotes from $GIT_DIR/remotes and from config file' '
+ cat >expect <<-EOF &&
+ remote_from_file_1
+ remote_from_file_2
+ remote_in_config_1
+ remote_in_config_2
+ EOF
+ test_when_finished "rm -rf .git/remotes" &&
+ mkdir -p .git/remotes &&
+ >.git/remotes/remote_from_file_1 &&
+ >.git/remotes/remote_from_file_2 &&
+ test_when_finished "git remote remove remote_in_config_1" &&
+ git remote add remote_in_config_1 git://remote_1 &&
+ test_when_finished "git remote remove remote_in_config_2" &&
+ git remote add remote_in_config_2 git://remote_2 &&
+ __git_remotes >actual &&
+ test_cmp expect actual
+'
+
test_expect_success 'basic' '
run_completion "git " &&
# built-in
diff --git a/t/t9903-bash-prompt.sh b/t/t9903-bash-prompt.sh
index 51ecd3e4c1..46d7d37a51 100755
--- a/t/t9903-bash-prompt.sh
+++ b/t/t9903-bash-prompt.sh
@@ -397,6 +397,17 @@ test_expect_success 'prompt - untracked files status indicator - untracked files
test_cmp expected "$actual"
'
+test_expect_success 'prompt - untracked files status indicator - untracked files outside cwd' '
+ printf " (master %%)" >expected &&
+ (
+ mkdir -p ignored_dir &&
+ cd ignored_dir &&
+ GIT_PS1_SHOWUNTRACKEDFILES=y &&
+ __git_ps1 >"$actual"
+ ) &&
+ test_cmp expected "$actual"
+'
+
test_expect_success 'prompt - untracked files status indicator - shell variable unset with config disabled' '
printf " (master)" >expected &&
test_config bash.showUntrackedFiles false &&
diff --git a/transport.c b/transport.c
index 08bcd3a4eb..88bde1d85e 100644
--- a/transport.c
+++ b/transport.c
@@ -117,7 +117,7 @@ static void insert_packed_refs(const char *packed_refs, struct ref **list)
return;
}
- if (hexval(buffer[0]) > 0xf)
+ if (!isxdigit(buffer[0]))
continue;
len = strlen(buffer);
if (len && buffer[len - 1] == '\n')
@@ -519,7 +519,7 @@ static int fetch_refs_via_pack(struct transport *transport,
int nr_heads, struct ref **to_fetch)
{
struct git_transport_data *data = transport->data;
- const struct ref *refs;
+ struct ref *refs;
char *dest = xstrdup(transport->url);
struct fetch_pack_args args;
struct ref *refs_tmp = NULL;
@@ -552,15 +552,17 @@ static int fetch_refs_via_pack(struct transport *transport,
&transport->pack_lockfile);
close(data->fd[0]);
close(data->fd[1]);
- if (finish_connect(data->conn))
+ if (finish_connect(data->conn)) {
+ free_refs(refs);
refs = NULL;
+ }
data->conn = NULL;
data->got_remote_heads = 0;
data->options.self_contained_and_connected =
args.self_contained_and_connected;
free_refs(refs_tmp);
-
+ free_refs(refs);
free(dest);
return (refs ? 0 : -1);
}
diff --git a/upload-pack.c b/upload-pack.c
index b531a325d2..aa84576500 100644
--- a/upload-pack.c
+++ b/upload-pack.c
@@ -681,7 +681,7 @@ static void receive_needs(void)
}
/* return non-zero if the ref is hidden, otherwise 0 */
-static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+static int mark_our_ref(const char *refname, const unsigned char *sha1)
{
struct object *o = lookup_unknown_object(sha1);
@@ -689,12 +689,16 @@ static int mark_our_ref(const char *refname, const unsigned char *sha1, int flag
o->flags |= HIDDEN_REF;
return 1;
}
- if (!o)
- die("git upload-pack: cannot find object %s:", sha1_to_hex(sha1));
o->flags |= OUR_REF;
return 0;
}
+static int check_ref(const char *refname, const unsigned char *sha1, int flag, void *cb_data)
+{
+ mark_our_ref(refname, sha1);
+ return 0;
+}
+
static void format_symref_info(struct strbuf *buf, struct string_list *symref)
{
struct string_list_item *item;
@@ -713,7 +717,7 @@ static int send_ref(const char *refname, const unsigned char *sha1, int flag, vo
const char *refname_nons = strip_namespace(refname);
unsigned char peeled[20];
- if (mark_our_ref(refname, sha1, flag, NULL))
+ if (mark_our_ref(refname, sha1))
return 0;
if (capabilities) {
@@ -767,8 +771,8 @@ static void upload_pack(void)
advertise_shallow_grafts(1);
packet_flush(1);
} else {
- head_ref_namespaced(mark_our_ref, NULL);
- for_each_namespaced_ref(mark_our_ref, NULL);
+ head_ref_namespaced(check_ref, NULL);
+ for_each_namespaced_ref(check_ref, NULL);
}
string_list_clear(&symref, 1);
if (advertise_refs)
diff --git a/zlib.c b/zlib.c
index 61e6df0fdc..4223f1a8c5 100644
--- a/zlib.c
+++ b/zlib.c
@@ -159,6 +159,7 @@ void git_deflate_init(git_zstream *strm, int level)
{
int status;
+ memset(strm, 0, sizeof(*strm));
zlib_pre_call(strm);
status = deflateInit(&strm->z, level);
zlib_post_call(strm);
@@ -172,6 +173,7 @@ static void do_git_deflate_init(git_zstream *strm, int level, int windowBits)
{
int status;
+ memset(strm, 0, sizeof(*strm));
zlib_pre_call(strm);
status = deflateInit2(&strm->z, level,
Z_DEFLATED, windowBits,