1
0
Fork 0
mirror of https://github.com/git/git.git synced 2024-06-10 22:46:21 +02:00

Merge branch 'jk/ref-paranoia' into jt/no-abuse-alternate-odb-for-submodules

* jk/ref-paranoia: (71 commits)
  refs: drop "broken" flag from for_each_fullref_in()
  ref-filter: drop broken-ref code entirely
  ref-filter: stop setting FILTER_REFS_INCLUDE_BROKEN
  repack, prune: drop GIT_REF_PARANOIA settings
  refs: turn on GIT_REF_PARANOIA by default
  refs: omit dangling symrefs when using GIT_REF_PARANOIA
  refs: add DO_FOR_EACH_OMIT_DANGLING_SYMREFS flag
  refs-internal.h: reorganize DO_FOR_EACH_* flag documentation
  refs-internal.h: move DO_FOR_EACH_* flags next to each other
  t5312: be more assertive about command failure
  t5312: test non-destructive repack
  t5312: create bogus ref as necessary
  t5312: drop "verbose" helper
  t5600: provide detached HEAD for corruption failures
  t5516: don't use HEAD ref for invalid ref-deletion tests
  t7900: clean up some more broken refs
  The eighth batch
  t0000: avoid masking git exit value through pipes
  tree-diff: fix leak when not HAVE_ALLOCA_H
  pack-revindex.h: correct the time complexity descriptions
  ...
This commit is contained in:
Junio C Hamano 2021-09-28 15:15:42 -07:00
commit b6b210c5e1
92 changed files with 966 additions and 474 deletions

View File

@ -48,6 +48,14 @@ UI, Workflows & Features
entire directory outside the sparse cone to be removed, which is
especially useful when the sparse patterns change.
* Taking advantage of the CGI interface, http-backend has been
updated to enable protocol v2 automatically when the other side
asks for it.
* The credential-cache helper has been adjusted to Windows.
* The error in "git help no-such-git-command" is handled better.
Performance, Internal Implementation, Development Support etc.
@ -119,6 +127,9 @@ Performance, Internal Implementation, Development Support etc.
ask the file descriptors open for packfiles to be closed immediately
before spawning commands that may trigger auto-gc.
* An oddball OPTION_ARGUMENT feature has been removed from the
parse-options API.
Fixes since v2.33
-----------------
@ -245,6 +256,17 @@ Fixes since v2.33
subsystem has been cleaned up.
(merge 35cf94eaf6 rs/no-mode-to-open-when-appending later to maint).
* "git update-ref --stdin" failed to flush its output as needed,
which potentially led the conversation to a deadlock.
(merge 7c1200745b ps/update-ref-batch-flush later to maint).
* When "git am --abort" fails to abort correctly, it still exited
with exit status of 0, which has been corrected.
(merge c5ead19ea2 en/am-abort-fix later to maint).
* Correct nr and alloc members of strvec struct to be of type size_t.
(merge 8d133a4653 jk/strvec-typefix later to maint).
* Other code cleanup, docfix, build fix, etc.
(merge 1d9c8daef8 ab/bundle-doc later to maint).
(merge 81483fe613 en/merge-strategy-docs later to maint).
@ -276,3 +298,8 @@ Fixes since v2.33
(merge 92a5d1c9b4 jc/prefix-filename-allocates later to maint).
(merge d9a65b6c0a rs/setup-use-xopen-and-xdup later to maint).
(merge e8f55568de jk/t5562-racefix later to maint).
(merge 8f0f110156 rs/drop-core-compression-vars later to maint).
(merge b6d8887d3d ma/doc-git-version later to maint).
(merge 66c0c44df6 cb/plug-leaks-in-alloca-emu-users later to maint).
(merge afb32e8101 kz/revindex-comment-fix later to maint).
(merge ae578de926 po/git-config-doc-mentions-help-c later to maint).

View File

@ -178,6 +178,8 @@ default. You can use `--no-utf8` to override this.
--abort::
Restore the original branch and abort the patching operation.
Revert contents of files involved in the am operation to their
pre-am state.
--quit::
Abort the patching operation but keep HEAD and the index

View File

@ -71,6 +71,9 @@ codes are:
On success, the command returns the exit code 0.
A list of all available configuration variables can be obtained using the
`git help --config` command.
[[OPTIONS]]
OPTIONS
-------

View File

@ -16,7 +16,9 @@ A simple CGI program to serve the contents of a Git repository to Git
clients accessing the repository over http:// and https:// protocols.
The program supports clients fetching using both the smart HTTP protocol
and the backwards-compatible dumb HTTP protocol, as well as clients
pushing using the smart HTTP protocol.
pushing using the smart HTTP protocol. It also supports Git's
more-efficient "v2" protocol if properly configured; see the
discussion of `GIT_PROTOCOL` in the ENVIRONMENT section below.
It verifies that the directory has the magic file
"git-daemon-export-ok", and it will refuse to export any Git directory
@ -77,6 +79,18 @@ Apache 2.x::
SetEnv GIT_PROJECT_ROOT /var/www/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/libexec/git-core/git-http-backend/
# This is not strictly necessary using Apache and a modern version of
# git-http-backend, as the webserver will pass along the header in the
# environment as HTTP_GIT_PROTOCOL, and http-backend will copy that into
# GIT_PROTOCOL. But you may need this line (or something similar if you
# are using a different webserver), or if you want to support older Git
# versions that did not do that copying.
#
# Having the webserver set up GIT_PROTOCOL is perfectly fine even with
# modern versions (and will take precedence over HTTP_GIT_PROTOCOL,
# which means it can be used to override the client's request).
SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
----------------------------------------------------------------
+
To enable anonymous read access but authenticated write access,
@ -264,6 +278,16 @@ a repository with an extremely large number of refs. The value can be
specified with a unit (e.g., `100M` for 100 megabytes). The default is
10 megabytes.
Clients may probe for optional protocol capabilities (like the v2
protocol) using the `Git-Protocol` HTTP header. In order to support
these, the contents of that header must appear in the `GIT_PROTOCOL`
environment variable. Most webservers will pass this header to the CGI
via the `HTTP_GIT_PROTOCOL` variable, and `git-http-backend` will
automatically copy that to `GIT_PROTOCOL`. However, some webservers may
be more selective about which headers they'll pass, in which case they
need to be configured explicitly (see the mention of `Git-Protocol` in
the Apache config from the earlier EXAMPLES section).
The backend process sets GIT_COMMITTER_NAME to '$REMOTE_USER' and
GIT_COMMITTER_EMAIL to '$\{REMOTE_USER}@http.$\{REMOTE_ADDR\}',
ensuring that any reflogs created by 'git-receive-pack' contain some

View File

@ -48,6 +48,14 @@ OPTIONS
<directory>::
The repository to sync from.
ENVIRONMENT
-----------
`GIT_PROTOCOL`::
Internal variable used for handshaking the wire protocol. Server
admins may need to configure some transports to allow this
variable to be passed. See the discussion in linkgit:git[1].
SEE ALSO
--------
linkgit:gitnamespaces[7]

View File

@ -0,0 +1,28 @@
git-version(1)
==============
NAME
----
git-version - Display version information about Git
SYNOPSIS
--------
[verse]
'git version' [--build-options]
DESCRIPTION
-----------
With no options given, the version of 'git' is printed on the standard output.
Note that `git --version` is identical to `git version` because the
former is internally converted into the latter.
OPTIONS
-------
--build-options::
Include additional information about how git was built for diagnostic
purposes.
GIT
---
Part of the linkgit:git[1] suite

View File

@ -41,6 +41,10 @@ OPTIONS
-------
--version::
Prints the Git suite version that the 'git' program came from.
+
This option is internaly converted to `git version ...` and accepts
the same options as the linkgit:git-version[1] command. If `--help` is
also given, it takes precedence over `--version`.
--help::
Prints the synopsis and a list of the most commonly used
@ -863,15 +867,16 @@ for full details.
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).
If set to `0`, ignore broken or badly named refs when iterating
over lists of refs. Normally Git will try to include any such
refs, which may cause some operations to fail. This is usually
preferable, as potentially destructive operations (e.g.,
linkgit:git-prune[1]) are better off aborting rather than
ignoring broken refs (and thus considering the history they
point to as not worth saving). The default value is `1` (i.e.,
be paranoid about detecting and aborting all operations). You
should not normally need to set this to `0`, but it may be
useful when trying to salvage data from a corrupted repository.
`GIT_ALLOW_PROTOCOL`::
If set to a colon-separated list of protocols, behave as if
@ -894,6 +899,21 @@ for full details.
Contains a colon ':' separated list of keys with optional values
'key[=value]'. Presence of unknown keys and values must be
ignored.
+
Note that servers may need to be configured to allow this variable to
pass over some transports. It will be propagated automatically when
accessing local repositories (i.e., `file://` or a filesystem path), as
well as over the `git://` protocol. For git-over-http, it should work
automatically in most configurations, but see the discussion in
linkgit:git-http-backend[1]. For git-over-ssh, the ssh server may need
to be configured to allow clients to pass this variable (e.g., by using
`AcceptEnv GIT_PROTOCOL` with OpenSSH).
+
This configuration is optional. If the variable is not propagated, then
clients will fall back to the original "v0" protocol (but may miss out
on some performance improvements or features). This variable currently
only affects clones and fetches; it is not yet used for pushes (but may
be in the future).
`GIT_OPTIONAL_LOCKS`::
If set to `0`, Git will complete any requested operation without

View File

@ -198,11 +198,6 @@ There are some macros to easily define options:
The filename will be prefixed by passing the filename along with
the prefix argument of `parse_options()` to `prefix_filename()`.
`OPT_ARGUMENT(long, &int_var, description)`::
Introduce a long-option argument that will be kept in `argv[]`.
If this option was seen, `int_var` will be set to one (except
if a `NULL` pointer was passed).
`OPT_NUMBER_CALLBACK(&var, description, func_ptr)`::
Recognize numerical options like -123 and feed the integer as
if it was an argument to the function given by `func_ptr`.

View File

@ -42,7 +42,8 @@ Initial Client Request
In general a client can request to speak protocol v2 by sending
`version=2` through the respective side-channel for the transport being
used which inevitably sets `GIT_PROTOCOL`. More information can be
found in `pack-protocol.txt` and `http-protocol.txt`. In all cases the
found in `pack-protocol.txt` and `http-protocol.txt`, as well as the
`GIT_PROTOCOL` definition in `git.txt`. In all cases the
response from the server is the capability advertisement.
Git Transport
@ -58,6 +59,8 @@ SSH and File Transport
When using either the ssh:// or file:// transport, the GIT_PROTOCOL
environment variable must be set explicitly to include "version=2".
The server may need to be configured to allow this environment variable
to pass.
HTTP Transport
~~~~~~~~~~~~~~
@ -84,6 +87,9 @@ Subsequent requests are then made directly to the service
Uses the `--http-backend-info-refs` option to
linkgit:git-upload-pack[1].
The server may need to be configured to pass this header's contents via
the `GIT_PROTOCOL` variable. See the discussion in `git-http-backend.txt`.
Capability Advertisement
------------------------

15
INSTALL
View File

@ -138,12 +138,15 @@ Issues of note:
BLK_SHA1. Also included is a version optimized for PowerPC
(PPC_SHA1).
- "libcurl" library is used by git-http-fetch, git-fetch, and, if
the curl version >= 7.34.0, for git-imap-send. You might also
want the "curl" executable for debugging purposes. If you do not
use http:// or https:// repositories, and do not want to put
patches into an IMAP mailbox, you do not have to have them
(use NO_CURL).
- "libcurl" library is used for fetching and pushing
repositories over http:// or https://, as well as by
git-imap-send if the curl version is >= 7.34.0. If you do
not need that functionality, use NO_CURL to build without
it.
Git requires version "7.19.4" or later of "libcurl" to build
without NO_CURL. This version requirement may be bumped in
the future.
- "expat" library; git-http-push uses it for remote lock
management over DAV. Similar to "curl" above, this is optional

View File

@ -1421,15 +1421,8 @@ else
REMOTE_CURL_NAMES = $(REMOTE_CURL_PRIMARY) $(REMOTE_CURL_ALIASES)
PROGRAM_OBJS += http-fetch.o
PROGRAMS += $(REMOTE_CURL_NAMES)
curl_check := $(shell (echo 070908; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "070908"
ifndef NO_EXPAT
PROGRAM_OBJS += http-push.o
else
EXCLUDED_PROGRAMS += git-http-push
endif
else
EXCLUDED_PROGRAMS += git-http-push
ifndef NO_EXPAT
PROGRAM_OBJS += http-push.o
endif
curl_check := $(shell (echo 072200; $(CURL_CONFIG) --vernum | sed -e '/^70[BC]/s/^/0/') 2>/dev/null | sort -r | sed -ne 2p)
ifeq "$(curl_check)" "072200"

View File

@ -2105,7 +2105,8 @@ static void am_abort(struct am_state *state)
if (!has_orig_head)
oidcpy(&orig_head, the_hash_algo->empty_tree);
clean_index(&curr_head, &orig_head);
if (clean_index(&curr_head, &orig_head))
die(_("failed to clean index"));
if (has_orig_head)
update_ref("am --abort", "HEAD", &orig_head,

View File

@ -18,10 +18,10 @@ static GIT_PATH_FUNC(git_path_bisect_log, "BISECT_LOG")
static GIT_PATH_FUNC(git_path_head_name, "head-name")
static GIT_PATH_FUNC(git_path_bisect_names, "BISECT_NAMES")
static GIT_PATH_FUNC(git_path_bisect_first_parent, "BISECT_FIRST_PARENT")
static GIT_PATH_FUNC(git_path_bisect_run, "BISECT_RUN")
static const char * const git_bisect_helper_usage[] = {
N_("git bisect--helper --bisect-reset [<commit>]"),
N_("git bisect--helper --bisect-next-check <good_term> <bad_term> [<term>]"),
N_("git bisect--helper --bisect-terms [--term-good | --term-old | --term-bad | --term-new]"),
N_("git bisect--helper --bisect-start [--term-{new,bad}=<term> --term-{old,good}=<term>]"
" [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<paths>...]"),
@ -30,6 +30,8 @@ static const char * const git_bisect_helper_usage[] = {
N_("git bisect--helper --bisect-state (good|old) [<rev>...]"),
N_("git bisect--helper --bisect-replay <filename>"),
N_("git bisect--helper --bisect-skip [(<rev>|<range>)...]"),
N_("git bisect--helper --bisect-visualize"),
N_("git bisect--helper --bisect-run <cmd>..."),
NULL
};
@ -143,6 +145,19 @@ static int append_to_file(const char *path, const char *format, ...)
return res;
}
static int print_file_to_stdout(const char *path)
{
int fd = open(path, O_RDONLY);
int ret = 0;
if (fd < 0)
return error_errno(_("cannot open file '%s' for reading"), path);
if (copy_fd(fd, 1) < 0)
ret = error_errno(_("failed to read '%s'"), path);
close(fd);
return ret;
}
static int check_term_format(const char *term, const char *orig_term)
{
int res;
@ -1036,6 +1051,125 @@ static enum bisect_error bisect_skip(struct bisect_terms *terms, const char **ar
return res;
}
static int bisect_visualize(struct bisect_terms *terms, const char **argv, int argc)
{
struct strvec args = STRVEC_INIT;
int flags = RUN_COMMAND_NO_STDIN, res = 0;
struct strbuf sb = STRBUF_INIT;
if (bisect_next_check(terms, NULL) != 0)
return BISECT_FAILED;
if (!argc) {
if ((getenv("DISPLAY") || getenv("SESSIONNAME") || getenv("MSYSTEM") ||
getenv("SECURITYSESSIONID")) && exists_in_PATH("gitk")) {
strvec_push(&args, "gitk");
} else {
strvec_push(&args, "log");
flags |= RUN_GIT_CMD;
}
} else {
if (argv[0][0] == '-') {
strvec_push(&args, "log");
flags |= RUN_GIT_CMD;
} else if (strcmp(argv[0], "tig") && !starts_with(argv[0], "git"))
flags |= RUN_GIT_CMD;
strvec_pushv(&args, argv);
}
strvec_pushl(&args, "--bisect", "--", NULL);
strbuf_read_file(&sb, git_path_bisect_names(), 0);
sq_dequote_to_strvec(sb.buf, &args);
strbuf_release(&sb);
res = run_command_v_opt(args.v, flags);
strvec_clear(&args);
return res;
}
static int bisect_run(struct bisect_terms *terms, const char **argv, int argc)
{
int res = BISECT_OK;
struct strbuf command = STRBUF_INIT;
struct strvec args = STRVEC_INIT;
struct strvec run_args = STRVEC_INIT;
const char *new_state;
int temporary_stdout_fd, saved_stdout;
if (bisect_next_check(terms, NULL))
return BISECT_FAILED;
if (argc)
sq_quote_argv(&command, argv);
else {
error(_("bisect run failed: no command provided."));
return BISECT_FAILED;
}
strvec_push(&run_args, command.buf);
while (1) {
strvec_clear(&args);
printf(_("running %s\n"), command.buf);
res = run_command_v_opt(run_args.v, RUN_USING_SHELL);
if (res < 0 || 128 <= res) {
error(_("bisect run failed: exit code %d from"
" '%s' is < 0 or >= 128"), res, command.buf);
strbuf_release(&command);
return res;
}
if (res == 125)
new_state = "skip";
else if (!res)
new_state = terms->term_good;
else
new_state = terms->term_bad;
temporary_stdout_fd = open(git_path_bisect_run(), O_CREAT | O_WRONLY | O_TRUNC, 0666);
if (temporary_stdout_fd < 0)
return error_errno(_("cannot open file '%s' for writing"), git_path_bisect_run());
fflush(stdout);
saved_stdout = dup(1);
dup2(temporary_stdout_fd, 1);
res = bisect_state(terms, &new_state, 1);
fflush(stdout);
dup2(saved_stdout, 1);
close(saved_stdout);
close(temporary_stdout_fd);
print_file_to_stdout(git_path_bisect_run());
if (res == BISECT_ONLY_SKIPPED_LEFT)
error(_("bisect run cannot continue any more"));
else if (res == BISECT_INTERNAL_SUCCESS_MERGE_BASE) {
printf(_("bisect run success"));
res = BISECT_OK;
} else if (res == BISECT_INTERNAL_SUCCESS_1ST_BAD_FOUND) {
printf(_("bisect found first bad commit"));
res = BISECT_OK;
} else if (res) {
error(_("bisect run failed:'git bisect--helper --bisect-state"
" %s' exited with error code %d"), args.v[0], res);
} else {
continue;
}
strbuf_release(&command);
strvec_clear(&args);
strvec_clear(&run_args);
return res;
}
}
int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
{
enum {
@ -1048,7 +1182,9 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
BISECT_STATE,
BISECT_LOG,
BISECT_REPLAY,
BISECT_SKIP
BISECT_SKIP,
BISECT_VISUALIZE,
BISECT_RUN,
} cmdmode = 0;
int res = 0, nolog = 0;
struct option options[] = {
@ -1070,6 +1206,10 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
N_("replay the bisection process from the given file"), BISECT_REPLAY),
OPT_CMDMODE(0, "bisect-skip", &cmdmode,
N_("skip some commits for checkout"), BISECT_SKIP),
OPT_CMDMODE(0, "bisect-visualize", &cmdmode,
N_("visualize the bisection"), BISECT_VISUALIZE),
OPT_CMDMODE(0, "bisect-run", &cmdmode,
N_("use <cmd>... to automatically bisect."), BISECT_RUN),
OPT_BOOL(0, "no-log", &nolog,
N_("no log for BISECT_WRITE")),
OPT_END()
@ -1089,12 +1229,6 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
return error(_("--bisect-reset requires either no argument or a commit"));
res = bisect_reset(argc ? argv[0] : NULL);
break;
case BISECT_NEXT_CHECK:
if (argc != 2 && argc != 3)
return error(_("--bisect-next-check requires 2 or 3 arguments"));
set_terms(&terms, argv[1], argv[0]);
res = bisect_next_check(&terms, argc == 3 ? argv[2] : NULL);
break;
case BISECT_TERMS:
if (argc > 1)
return error(_("--bisect-terms requires 0 or 1 argument"));
@ -1131,6 +1265,16 @@ int cmd_bisect__helper(int argc, const char **argv, const char *prefix)
get_terms(&terms);
res = bisect_skip(&terms, argv, argc);
break;
case BISECT_VISUALIZE:
get_terms(&terms);
res = bisect_visualize(&terms, argv, argc);
break;
case BISECT_RUN:
if (!argc)
return error(_("bisect run failed: no command provided."));
get_terms(&terms);
res = bisect_run(&terms, argv, argc);
break;
default:
BUG("unknown subcommand %d", cmdmode);
}

View File

@ -427,7 +427,7 @@ static void print_ref_list(struct ref_filter *filter, struct ref_sorting *sortin
memset(&array, 0, sizeof(array));
filter_refs(&array, filter, filter->kind | FILTER_REFS_INCLUDE_BROKEN);
filter_refs(&array, filter, filter->kind);
if (filter->verbose)
maxwidth = calc_maxwidth(&array, strlen(remote_prefix));

View File

@ -11,6 +11,32 @@
#define FLAG_SPAWN 0x1
#define FLAG_RELAY 0x2
#ifdef GIT_WINDOWS_NATIVE
static int connection_closed(int error)
{
return (error == EINVAL);
}
static int connection_fatally_broken(int error)
{
return (error != ENOENT) && (error != ENETDOWN);
}
#else
static int connection_closed(int error)
{
return (error == ECONNRESET);
}
static int connection_fatally_broken(int error)
{
return (error != ENOENT) && (error != ECONNREFUSED);
}
#endif
static int send_request(const char *socket, const struct strbuf *out)
{
int got_data = 0;
@ -28,7 +54,7 @@ static int send_request(const char *socket, const struct strbuf *out)
int r;
r = read_in_full(fd, in, sizeof(in));
if (r == 0 || (r < 0 && errno == ECONNRESET))
if (r == 0 || (r < 0 && connection_closed(errno)))
break;
if (r < 0)
die_errno("read error from cache daemon");
@ -75,7 +101,7 @@ static void do_cache(const char *socket, const char *action, int timeout,
}
if (send_request(socket, &buf) < 0) {
if (errno != ENOENT && errno != ECONNREFUSED)
if (connection_fatally_broken(errno))
die_errno("unable to connect to cache daemon");
if (flags & FLAG_SPAWN) {
spawn_daemon(socket);

View File

@ -331,7 +331,7 @@ static int checkout_path(unsigned mode, struct object_id *oid,
}
static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
int argc, const char **argv)
struct child_process *child)
{
char tmpdir[PATH_MAX];
struct strbuf info = STRBUF_INIT, lpath = STRBUF_INIT;
@ -352,7 +352,6 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
struct index_state wtindex;
struct checkout lstate, rstate;
int rc, flags = RUN_GIT_CMD, err = 0;
struct child_process child = CHILD_PROCESS_INIT;
const char *helper_argv[] = { "difftool--helper", NULL, NULL, NULL };
struct hashmap wt_modified, tmp_modified;
int indices_loaded = 0;
@ -387,19 +386,15 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
rdir_len = rdir.len;
wtdir_len = wtdir.len;
child.no_stdin = 1;
child.git_cmd = 1;
child.use_shell = 0;
child.clean_on_exit = 1;
child.dir = prefix;
child.out = -1;
strvec_pushl(&child.args, "diff", "--raw", "--no-abbrev", "-z",
NULL);
for (i = 0; i < argc; i++)
strvec_push(&child.args, argv[i]);
if (start_command(&child))
child->no_stdin = 1;
child->git_cmd = 1;
child->use_shell = 0;
child->clean_on_exit = 1;
child->dir = prefix;
child->out = -1;
if (start_command(child))
die("could not obtain raw diff");
fp = xfdopen(child.out, "r");
fp = xfdopen(child->out, "r");
/* Build index info for left and right sides of the diff */
i = 0;
@ -525,7 +520,7 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
fclose(fp);
fp = NULL;
if (finish_command(&child)) {
if (finish_command(child)) {
ret = error("error occurred running diff --raw");
goto finish;
}
@ -668,25 +663,23 @@ static int run_dir_diff(const char *extcmd, int symlinks, const char *prefix,
}
static int run_file_diff(int prompt, const char *prefix,
int argc, const char **argv)
struct child_process *child)
{
struct strvec args = STRVEC_INIT;
const char *env[] = {
"GIT_PAGER=", "GIT_EXTERNAL_DIFF=git-difftool--helper", NULL,
NULL
};
int i;
if (prompt > 0)
env[2] = "GIT_DIFFTOOL_PROMPT=true";
else if (!prompt)
env[2] = "GIT_DIFFTOOL_NO_PROMPT=true";
child->git_cmd = 1;
child->dir = prefix;
strvec_pushv(&child->env_array, env);
strvec_push(&args, "diff");
for (i = 0; i < argc; i++)
strvec_push(&args, argv[i]);
return run_command_v_opt_cd_env(args.v, RUN_GIT_CMD, prefix, env);
return run_command(child);
}
int cmd_difftool(int argc, const char **argv, const char *prefix)
@ -716,9 +709,10 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
"tool returns a non - zero exit code")),
OPT_STRING('x', "extcmd", &extcmd, N_("command"),
N_("specify a custom command for viewing diffs")),
OPT_ARGUMENT("no-index", &no_index, N_("passed to `diff`")),
OPT_BOOL(0, "no-index", &no_index, N_("passed to `diff`")),
OPT_END()
};
struct child_process child = CHILD_PROCESS_INIT;
git_config(difftool_config, NULL);
symlinks = has_symlinks;
@ -768,7 +762,14 @@ int cmd_difftool(int argc, const char **argv, const char *prefix)
* will invoke a separate instance of 'git-difftool--helper' for
* each file that changed.
*/
strvec_push(&child.args, "diff");
if (no_index)
strvec_push(&child.args, "--no-index");
if (dir_diff)
return run_dir_diff(extcmd, symlinks, prefix, argc, argv);
return run_file_diff(prompt, prefix, argc, argv);
strvec_pushl(&child.args, "--raw", "--no-abbrev", "-z", NULL);
strvec_pushv(&child.args, argv);
if (dir_diff)
return run_dir_diff(extcmd, symlinks, prefix, &child);
return run_file_diff(prompt, prefix, &child);
}

View File

@ -77,7 +77,7 @@ int cmd_for_each_ref(int argc, const char **argv, const char *prefix)
filter.name_patterns = argv;
filter.match_as_path = 1;
filter_refs(&array, &filter, FILTER_REFS_ALL | FILTER_REFS_INCLUDE_BROKEN);
filter_refs(&array, &filter, FILTER_REFS_ALL);
ref_array_sort(sorting, &array);
if (!maxcount || array.nr < maxcount)

View File

@ -1681,9 +1681,7 @@ static int launchctl_remove_plists(void)
static int launchctl_list_contains_plist(const char *name, const char *cmd)
{
int result;
struct child_process child = CHILD_PROCESS_INIT;
char *uid = launchctl_get_uid();
strvec_split(&child.args, cmd);
strvec_pushl(&child.args, "list", name, NULL);
@ -1694,12 +1692,8 @@ static int launchctl_list_contains_plist(const char *name, const char *cmd)
if (start_command(&child))
die(_("failed to start launchctl"));
result = finish_command(&child);
free(uid);
/* Returns failure if 'name' doesn't exist. */
return !result;
return !finish_command(&child);
}
static int launchctl_schedule_plist(const char *exec_path, enum schedule_priority schedule)

View File

@ -467,11 +467,14 @@ static void get_html_page_path(struct strbuf *page_path, const char *page)
if (!html_path)
html_path = to_free = system_path(GIT_HTML_PATH);
/* Check that we have a git documentation directory. */
/*
* Check that the page we're looking for exists.
*/
if (!strstr(html_path, "://")) {
if (stat(mkpath("%s/git.html", html_path), &st)
if (stat(mkpath("%s/%s.html", html_path, page), &st)
|| !S_ISREG(st.st_mode))
die("'%s': not a documentation directory.", html_path);
die("'%s/%s.html': documentation file not found.",
html_path, page);
}
strbuf_init(page_path, 0);

View File

@ -188,9 +188,7 @@ static void init_thread(void)
pthread_key_create(&key, NULL);
CALLOC_ARRAY(thread_data, nr_threads);
for (i = 0; i < nr_threads; i++) {
thread_data[i].pack_fd = open(curr_pack, O_RDONLY);
if (thread_data[i].pack_fd == -1)
die_errno(_("unable to open %s"), curr_pack);
thread_data[i].pack_fd = xopen(curr_pack, O_RDONLY);
}
threads_active = 1;

View File

@ -143,7 +143,6 @@ int cmd_prune(int argc, const char **argv, const char *prefix)
expire = TIME_MAX;
save_commit_buffer = 0;
read_replace_refs = 0;
ref_paranoia = 1;
repo_init_revisions(the_repository, &revs, prefix);
argc = parse_options(argc, argv, prefix, options, prune_usage, 0);

View File

@ -586,15 +586,12 @@ int cmd_repack(int argc, const char **argv, const char *prefix)
strvec_pushf(&cmd.args,
"--unpack-unreachable=%s",
unpack_unreachable);
strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
} else if (pack_everything & LOOSEN_UNREACHABLE) {
strvec_push(&cmd.args,
"--unpack-unreachable");
} else if (keep_unreachable) {
strvec_push(&cmd.args, "--keep-unreachable");
strvec_push(&cmd.args, "--pack-loose-unreachable");
} else {
strvec_push(&cmd.env_array, "GIT_REF_PARANOIA=1");
}
}
} else if (geometry) {

View File

@ -863,8 +863,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
continue;
}
if (!strcmp(arg, "--bisect")) {
for_each_fullref_in("refs/bisect/bad", show_reference, NULL, 0);
for_each_fullref_in("refs/bisect/good", anti_reference, NULL, 0);
for_each_fullref_in("refs/bisect/bad", show_reference, NULL);
for_each_fullref_in("refs/bisect/good", anti_reference, NULL);
continue;
}
if (opt_with_value(arg, "--branches", &arg)) {

View File

@ -1668,18 +1668,24 @@ static int add_possible_reference_from_superproject(
* standard layout with .git/(modules/<name>)+/objects
*/
if (strip_suffix(odb->path, "/objects", &len)) {
struct repository alternate;
char *sm_alternate;
struct strbuf sb = STRBUF_INIT;
struct strbuf err = STRBUF_INIT;
strbuf_add(&sb, odb->path, len);
repo_init(&alternate, sb.buf, NULL);
/*
* We need to end the new path with '/' to mark it as a dir,
* otherwise a submodule name containing '/' will be broken
* as the last part of a missing submodule reference would
* be taken as a file name.
*/
strbuf_addf(&sb, "/modules/%s/", sas->submodule_name);
strbuf_reset(&sb);
submodule_name_to_gitdir(&sb, &alternate, sas->submodule_name);
strbuf_addch(&sb, '/');
repo_clear(&alternate);
sm_alternate = compute_alternate_path(sb.buf, &err);
if (sm_alternate) {
@ -1749,7 +1755,7 @@ static int clone_submodule(struct module_clone_data *clone_data)
struct strbuf sb = STRBUF_INIT;
struct child_process cp = CHILD_PROCESS_INIT;
strbuf_addf(&sb, "%s/modules/%s", get_git_dir(), clone_data->name);
submodule_name_to_gitdir(&sb, the_repository, clone_data->name);
sm_gitdir = absolute_pathdup(sb.buf);
strbuf_reset(&sb);

View File

@ -302,6 +302,12 @@ static void parse_cmd_verify(struct ref_transaction *transaction,
strbuf_release(&err);
}
static void report_ok(const char *command)
{
fprintf(stdout, "%s: ok\n", command);
fflush(stdout);
}
static void parse_cmd_option(struct ref_transaction *transaction,
const char *next, const char *end)
{
@ -317,7 +323,7 @@ static void parse_cmd_start(struct ref_transaction *transaction,
{
if (*next != line_termination)
die("start: extra input: %s", next);
puts("start: ok");
report_ok("start");
}
static void parse_cmd_prepare(struct ref_transaction *transaction,
@ -328,7 +334,7 @@ static void parse_cmd_prepare(struct ref_transaction *transaction,
die("prepare: extra input: %s", next);
if (ref_transaction_prepare(transaction, &error))
die("prepare: %s", error.buf);
puts("prepare: ok");
report_ok("prepare");
}
static void parse_cmd_abort(struct ref_transaction *transaction,
@ -339,7 +345,7 @@ static void parse_cmd_abort(struct ref_transaction *transaction,
die("abort: extra input: %s", next);
if (ref_transaction_abort(transaction, &error))
die("abort: %s", error.buf);
puts("abort: ok");
report_ok("abort");
}
static void parse_cmd_commit(struct ref_transaction *transaction,
@ -350,7 +356,7 @@ static void parse_cmd_commit(struct ref_transaction *transaction,
die("commit: extra input: %s", next);
if (ref_transaction_commit(transaction, &error))
die("commit: %s", error.buf);
puts("commit: ok");
report_ok("commit");
ref_transaction_free(transaction);
}

View File

@ -958,7 +958,6 @@ extern char *apply_default_ignorewhitespace;
extern const char *git_attributes_file;
extern const char *git_hooks_path;
extern int zlib_compression_level;
extern int core_compression_level;
extern int pack_compression_level;
extern size_t packed_git_window_size;
extern size_t packed_git_limit;
@ -995,14 +994,6 @@ extern const char *core_fsmonitor;
extern int core_apply_sparse_checkout;
extern int core_sparse_checkout_cone;
/*
* 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;
/*
* Returns the boolean value of $GIT_OPTIONAL_LOCKS (or the default value).
*/

View File

@ -76,7 +76,6 @@ static struct key_value_info *current_config_kvi;
*/
static enum config_scope current_parsing_scope;
static int core_compression_seen;
static int pack_compression_seen;
static int zlib_compression_seen;
@ -1400,8 +1399,6 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
level = Z_DEFAULT_COMPRESSION;
else if (level < 0 || level > Z_BEST_COMPRESSION)
die(_("bad zlib compression level %d"), level);
core_compression_level = level;
core_compression_seen = 1;
if (!zlib_compression_seen)
zlib_compression_level = level;
if (!pack_compression_seen)

View File

@ -2,15 +2,18 @@
identifier fd;
identifier die_fn =~ "^(die|die_errno)$";
@@
(
fd =
- open
+ xopen
(...);
|
int fd =
- open
+ xopen
(...);
)
- if ( \( fd < 0 \| fd == -1 \) ) { die_fn(...); }
@@
expression fd;
identifier die_fn =~ "^(die|die_errno)$";
@@
fd =
- open
+ xopen
(...);
- if ( \( fd < 0 \| fd == -1 \) ) { die_fn(...); }

2
dir.c
View File

@ -3799,7 +3799,7 @@ static void connect_wt_gitdir_in_nested(const char *sub_worktree,
strbuf_reset(&sub_wt);
strbuf_reset(&sub_gd);
strbuf_addf(&sub_wt, "%s/%s", sub_worktree, sub->path);
strbuf_addf(&sub_gd, "%s/modules/%s", sub_gitdir, sub->name);
submodule_name_to_gitdir(&sub_gd, &subrepo, sub->name);
connect_work_tree_and_git_dir(sub_wt.buf, sub_gd.buf, 1);
}

View File

@ -31,7 +31,6 @@ int prefer_symlink_refs;
int is_bare_repository_cfg = -1; /* unspecified */
int warn_ambiguous_refs = 1;
int warn_on_object_refname_ambiguity = 1;
int ref_paranoia = -1;
int repository_format_precious_objects;
int repository_format_worktree_config;
const char *git_commit_encoding;
@ -41,7 +40,6 @@ char *apply_default_ignorewhitespace;
const char *git_attributes_file;
const char *git_hooks_path;
int zlib_compression_level = Z_BEST_SPEED;
int core_compression_level;
int pack_compression_level = Z_DEFAULT_COMPRESSION;
int fsync_object_files;
size_t packed_git_window_size = DEFAULT_PACKED_GIT_WINDOW_SIZE;

View File

@ -34,94 +34,9 @@ Please use "git help bisect" to get the full man page.'
OPTIONS_SPEC=
. git-sh-setup
_x40='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x40="$_x40$_x40$_x40$_x40$_x40$_x40$_x40$_x40"
TERM_BAD=bad
TERM_GOOD=good
bisect_visualize() {
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
if test $# = 0
then
if test -n "${DISPLAY+set}${SESSIONNAME+set}${MSYSTEM+set}${SECURITYSESSIONID+set}" &&
type gitk >/dev/null 2>&1
then
set gitk
else
set git log
fi
else
case "$1" in
git*|tig) ;;
-*) set git log "$@" ;;
*) set git "$@" ;;
esac
fi
eval '"$@"' --bisect -- $(cat "$GIT_DIR/BISECT_NAMES")
}
bisect_run () {
git bisect--helper --bisect-next-check $TERM_GOOD $TERM_BAD fail || exit
test -n "$*" || die "$(gettext "bisect run failed: no command provided.")"
while true
do
command="$@"
eval_gettextln "running \$command"
"$@"
res=$?
# Check for really bad run error.
if [ $res -lt 0 -o $res -ge 128 ]
then
eval_gettextln "bisect run failed:
exit code \$res from '\$command' is < 0 or >= 128" >&2
exit $res
fi
# Find current state depending on run success or failure.
# A special exit code of 125 means cannot test.
if [ $res -eq 125 ]
then
state='skip'
elif [ $res -gt 0 ]
then
state="$TERM_BAD"
else
state="$TERM_GOOD"
fi
git bisect--helper --bisect-state $state >"$GIT_DIR/BISECT_RUN"
res=$?
cat "$GIT_DIR/BISECT_RUN"
if sane_grep "first $TERM_BAD commit could be any of" "$GIT_DIR/BISECT_RUN" \
>/dev/null
then
gettextln "bisect run cannot continue any more" >&2
exit $res
fi
if [ $res -ne 0 ]
then
eval_gettextln "bisect run failed:
'bisect-state \$state' exited with error code \$res" >&2
exit $res
fi
if sane_grep "is the first $TERM_BAD commit" "$GIT_DIR/BISECT_RUN" >/dev/null
then
gettextln "bisect run success"
exit 0;
fi
done
}
get_terms () {
if test -s "$GIT_DIR/BISECT_TERMS"
then
@ -152,7 +67,7 @@ case "$#" in
# Not sure we want "next" at the UI level anymore.
git bisect--helper --bisect-next "$@" || exit ;;
visualize|view)
bisect_visualize "$@" ;;
git bisect--helper --bisect-visualize "$@" || exit;;
reset)
git bisect--helper --bisect-reset "$@" ;;
replay)
@ -160,7 +75,7 @@ case "$#" in
log)
git bisect--helper --bisect-log || exit ;;
run)
bisect_run "$@" ;;
git bisect--helper --bisect-run "$@" || exit;;
terms)
git bisect--helper --bisect-terms "$@" || exit;;
*)

View File

@ -160,6 +160,9 @@
# endif
#define WIN32_LEAN_AND_MEAN /* stops windows.h including winsock.h */
#include <winsock2.h>
#ifndef NO_UNIX_SOCKETS
#include <afunix.h>
#endif
#include <windows.h>
#define GIT_WINDOWS_NATIVE
#endif

128
git-curl-compat.h Normal file
View File

@ -0,0 +1,128 @@
#ifndef GIT_CURL_COMPAT_H
#define GIT_CURL_COMPAT_H
#include <curl/curl.h>
/**
* This header centralizes the declaration of our libcurl dependencies
* to make it easy to discover the oldest versions we support, and to
* inform decisions about removing support for older libcurl in the
* future.
*
* The oldest supported version of curl is documented in the "INSTALL"
* document.
*
* The source of truth for what versions have which symbols is
* https://github.com/curl/curl/blob/master/docs/libcurl/symbols-in-versions;
* the release dates are taken from curl.git (at
* https://github.com/curl/curl/).
*
* For each X symbol we need from curl we define our own
* GIT_CURL_HAVE_X. If multiple similar symbols with the same prefix
* were defined in the same version we pick one and check for that name.
*
* We may also define a missing CURL_* symbol to its known value, if
* doing so is sufficient to add support for it to older versions that
* don't have it.
*
* Keep any symbols in date order of when their support was
* introduced, oldest first, in the official version of cURL library.
*/
/**
* CURL_SOCKOPT_OK was added in 7.21.5, released in April 2011.
*/
#if LIBCURL_VERSION_NUM < 0x071505
#define CURL_SOCKOPT_OK 0
#endif
/**
* CURLOPT_TCP_KEEPALIVE was added in 7.25.0, released in March 2012.
*/
#if LIBCURL_VERSION_NUM >= 0x071900
#define GITCURL_HAVE_CURLOPT_TCP_KEEPALIVE 1
#endif
/**
* CURLOPT_LOGIN_OPTIONS was added in 7.34.0, released in December
* 2013.
*
* If we start requiring 7.34.0 we might also be able to remove the
* code conditional on USE_CURL_FOR_IMAP_SEND in imap-send.c, see
* 1e16b255b95 (git-imap-send: use libcurl for implementation,
* 2014-11-09) and the check it added for "072200" in the Makefile.
*/
#if LIBCURL_VERSION_NUM >= 0x072200
#define GIT_CURL_HAVE_CURLOPT_LOGIN_OPTIONS 1
#endif
/**
* CURL_SSLVERSION_TLSv1_[012] was added in 7.34.0, released in
* December 2013.
*/
#if LIBCURL_VERSION_NUM >= 0x072200
#define GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_0
#endif
/**
* CURLOPT_PINNEDPUBLICKEY was added in 7.39.0, released in November
* 2014.
*/
#if LIBCURL_VERSION_NUM >= 0x072c00
#define GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY 1
#endif
/**
* CURL_HTTP_VERSION_2 was added in 7.43.0, released in June 2015.
*
* The CURL_HTTP_VERSION_2 alias (but not CURL_HTTP_VERSION_2_0) has
* always been a macro, not an enum field (checked on curl version
* 7.78.0)
*/
#if LIBCURL_VERSION_NUM >= 0x072b00
#define GIT_CURL_HAVE_CURL_HTTP_VERSION_2 1
#endif
/**
* CURLSSLOPT_NO_REVOKE was added in 7.44.0, released in August 2015.
*
* The CURLSSLOPT_NO_REVOKE is, has always been a macro, not an enum
* field (checked on curl version 7.78.0)
*/
#if LIBCURL_VERSION_NUM >= 0x072c00
#define GIT_CURL_HAVE_CURLSSLOPT_NO_REVOKE 1
#endif
/**
* CURLOPT_PROXY_CAINFO was added in 7.52.0, released in August 2017.
*/
#if LIBCURL_VERSION_NUM >= 0x073400
#define GIT_CURL_HAVE_CURLOPT_PROXY_CAINFO 1
#endif
/**
* CURLOPT_PROXY_{KEYPASSWD,SSLCERT,SSLKEY} was added in 7.52.0,
* released in August 2017.
*/
#if LIBCURL_VERSION_NUM >= 0x073400
#define GIT_CURL_HAVE_CURLOPT_PROXY_KEYPASSWD 1
#endif
/**
* CURL_SSLVERSION_TLSv1_3 was added in 7.53.0, released in February
* 2017.
*/
#if LIBCURL_VERSION_NUM >= 0x073400
#define GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_3 1
#endif
/**
* CURLSSLSET_{NO_BACKENDS,OK,TOO_LATE,UNKNOWN_BACKEND} were added in
* 7.56.0, released in September 2017.
*/
#if LIBCURL_VERSION_NUM >= 0x073800
#define GIT_CURL_HAVE_CURLSSLSET_NO_BACKENDS
#endif
#endif

View File

@ -223,9 +223,6 @@ require_clean_work_tree () {
"rewrite branches")
gettextln "Cannot rewrite branches: You have unstaged changes." >&2
;;
"pull with rebase")
gettextln "Cannot pull with rebase: You have unstaged changes." >&2
;;
*)
eval_gettextln "Cannot \$action: You have unstaged changes." >&2
;;
@ -242,9 +239,6 @@ require_clean_work_tree () {
rebase)
gettextln "Cannot rebase: Your index contains uncommitted changes." >&2
;;
"pull with rebase")
gettextln "Cannot pull with rebase: Your index contains uncommitted changes." >&2
;;
*)
eval_gettextln "Cannot \$action: Your index contains uncommitted changes." >&2
;;

View File

@ -63,11 +63,6 @@ isnumber()
n=$(($1 + 0)) 2>/dev/null && test "$n" = "$1"
}
# Given a full hex object ID, is this the zero OID?
is_zero_oid () {
echo "$1" | sane_egrep '^0+$' >/dev/null 2>&1
}
# Sanitize the local git environment for use within a submodule. We
# can't simply use clear_local_git_env since we want to preserve some
# of the settings from GIT_CONFIG_PARAMETERS.

View File

@ -739,6 +739,7 @@ static int bad_request(struct strbuf *hdr, const struct service_cmd *c)
int cmd_main(int argc, const char **argv)
{
char *method = getenv("REQUEST_METHOD");
const char *proto_header;
char *dir;
struct service_cmd *cmd = NULL;
char *cmd_arg = NULL;
@ -789,6 +790,9 @@ int cmd_main(int argc, const char **argv)
http_config();
max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
max_request_buffer);
proto_header = getenv("HTTP_GIT_PROTOCOL");
if (proto_header)
setenv(GIT_PROTOCOL_ENVIRONMENT, proto_header, 0);
cmd->imp(&hdr, cmd_arg);
return 0;

35
http.c
View File

@ -1,4 +1,5 @@
#include "git-compat-util.h"
#include "git-curl-compat.h"
#include "http.h"
#include "config.h"
#include "pack.h"
@ -47,19 +48,19 @@ static struct {
{ "sslv2", CURL_SSLVERSION_SSLv2 },
{ "sslv3", CURL_SSLVERSION_SSLv3 },
{ "tlsv1", CURL_SSLVERSION_TLSv1 },
#if LIBCURL_VERSION_NUM >= 0x072200
#ifdef GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_0
{ "tlsv1.0", CURL_SSLVERSION_TLSv1_0 },
{ "tlsv1.1", CURL_SSLVERSION_TLSv1_1 },
{ "tlsv1.2", CURL_SSLVERSION_TLSv1_2 },
#endif
#if LIBCURL_VERSION_NUM >= 0x073400
#ifdef GIT_CURL_HAVE_CURL_SSLVERSION_TLSv1_3
{ "tlsv1.3", CURL_SSLVERSION_TLSv1_3 },
#endif
};
static const char *ssl_key;
static const char *ssl_capath;
static const char *curl_no_proxy;
#if LIBCURL_VERSION_NUM >= 0x072c00
#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
static const char *ssl_pinnedkey;
#endif
static const char *ssl_cainfo;
@ -373,10 +374,10 @@ static int http_options(const char *var, const char *value, void *cb)
}
if (!strcmp("http.pinnedpubkey", var)) {
#if LIBCURL_VERSION_NUM >= 0x072c00
#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
return git_config_pathname(&ssl_pinnedkey, var, value);
#else
warning(_("Public key pinning not supported with cURL < 7.44.0"));
warning(_("Public key pinning not supported with cURL < 7.39.0"));
return 0;
#endif
}
@ -500,7 +501,7 @@ static int has_cert_password(void)
return 1;
}
#if LIBCURL_VERSION_NUM >= 0x073400
#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_KEYPASSWD
static int has_proxy_cert_password(void)
{
if (http_proxy_ssl_cert == NULL || proxy_ssl_cert_password_required != 1)
@ -516,7 +517,7 @@ static int has_proxy_cert_password(void)
}
#endif
#if LIBCURL_VERSION_NUM >= 0x071900
#ifdef GITCURL_HAVE_CURLOPT_TCP_KEEPALIVE
static void set_curl_keepalive(CURL *c)
{
curl_easy_setopt(c, CURLOPT_TCP_KEEPALIVE, 1);
@ -536,7 +537,7 @@ static int sockopt_callback(void *client, curl_socket_t fd, curlsocktype type)
if (rc < 0)
warning_errno("unable to set SO_KEEPALIVE on socket");
return 0; /* CURL_SOCKOPT_OK only exists since curl 7.21.5 */
return CURL_SOCKOPT_OK;
}
static void set_curl_keepalive(CURL *c)
@ -732,7 +733,7 @@ static long get_curl_allowed_protocols(int from_user)
return allowed_protocols;
}
#if LIBCURL_VERSION_NUM >=0x072f00
#ifdef GIT_CURL_HAVE_CURL_HTTP_VERSION_2
static int get_curl_http_version_opt(const char *version_string, long *opt)
{
int i;
@ -774,7 +775,7 @@ static CURL *get_curl_handle(void)
curl_easy_setopt(result, CURLOPT_SSL_VERIFYHOST, 2);
}
#if LIBCURL_VERSION_NUM >= 0x072f00 // 7.47.0
#ifdef GIT_CURL_HAVE_CURL_HTTP_VERSION_2
if (curl_http_version) {
long opt;
if (!get_curl_http_version_opt(curl_http_version, &opt)) {
@ -805,7 +806,7 @@ static CURL *get_curl_handle(void)
if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
!http_schannel_check_revoke) {
#if LIBCURL_VERSION_NUM >= 0x072c00
#ifdef GIT_CURL_HAVE_CURLSSLOPT_NO_REVOKE
curl_easy_setopt(result, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NO_REVOKE);
#else
warning(_("CURLSSLOPT_NO_REVOKE not supported with cURL < 7.44.0"));
@ -845,20 +846,20 @@ static CURL *get_curl_handle(void)
curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
if (ssl_capath != NULL)
curl_easy_setopt(result, CURLOPT_CAPATH, ssl_capath);
#if LIBCURL_VERSION_NUM >= 0x072c00
#ifdef GIT_CURL_HAVE_CURLOPT_PINNEDPUBLICKEY
if (ssl_pinnedkey != NULL)
curl_easy_setopt(result, CURLOPT_PINNEDPUBLICKEY, ssl_pinnedkey);
#endif
if (http_ssl_backend && !strcmp("schannel", http_ssl_backend) &&
!http_schannel_use_ssl_cainfo) {
curl_easy_setopt(result, CURLOPT_CAINFO, NULL);
#if LIBCURL_VERSION_NUM >= 0x073400
#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_CAINFO
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, NULL);
#endif
} else if (ssl_cainfo != NULL || http_proxy_ssl_ca_info != NULL) {
if (ssl_cainfo != NULL)
curl_easy_setopt(result, CURLOPT_CAINFO, ssl_cainfo);
#if LIBCURL_VERSION_NUM >= 0x073400
#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_CAINFO
if (http_proxy_ssl_ca_info != NULL)
curl_easy_setopt(result, CURLOPT_PROXY_CAINFO, http_proxy_ssl_ca_info);
#endif
@ -927,7 +928,6 @@ static CURL *get_curl_handle(void)
*/
curl_easy_setopt(result, CURLOPT_PROXY, "");
} else if (curl_http_proxy) {
#if LIBCURL_VERSION_NUM >= 0x071800
if (starts_with(curl_http_proxy, "socks5h"))
curl_easy_setopt(result,
CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5_HOSTNAME);
@ -940,8 +940,7 @@ static CURL *get_curl_handle(void)
else if (starts_with(curl_http_proxy, "socks"))
curl_easy_setopt(result,
CURLOPT_PROXYTYPE, CURLPROXY_SOCKS4);
#endif
#if LIBCURL_VERSION_NUM >= 0x073400
#ifdef GIT_CURL_HAVE_CURLOPT_PROXY_KEYPASSWD
else if (starts_with(curl_http_proxy, "https")) {
curl_easy_setopt(result, CURLOPT_PROXYTYPE, CURLPROXY_HTTPS);
@ -1006,7 +1005,7 @@ void http_init(struct remote *remote, const char *url, int proactive_auth)
free(normalized_url);
string_list_clear(&config.vars, 1);
#if LIBCURL_VERSION_NUM >= 0x073800
#ifdef GIT_CURL_HAVE_CURLSSLSET_NO_BACKENDS
if (http_ssl_backend) {
const curl_ssl_backend **backends;
struct strbuf buf = STRBUF_INIT;

View File

@ -1441,7 +1441,7 @@ static CURL *setup_curl(struct imap_server_conf *srvc, struct credential *cred)
curl_easy_setopt(curl, CURLOPT_PORT, server.port);
if (server.auth_method) {
#if LIBCURL_VERSION_NUM < 0x072200
#ifndef GIT_CURL_HAVE_CURLOPT_LOGIN_OPTIONS
warning("No LOGIN_OPTIONS support in this cURL version");
#else
struct strbuf auth = STRBUF_INIT;

View File

@ -171,7 +171,7 @@ int ls_refs(struct repository *r, struct packet_reader *request)
if (!data.prefixes.nr)
strvec_push(&data.prefixes, "");
for_each_fullref_in_prefixes(get_git_namespace(), data.prefixes.v,
send_ref, &data, 0);
send_ref, &data);
packet_fflush(stdout);
strvec_clear(&data.prefixes);
strbuf_release(&data.buf);

37
midx.c
View File

@ -283,14 +283,18 @@ uint32_t nth_midxed_pack_int_id(struct multi_pack_index *m, uint32_t pos)
(off_t)pos * MIDX_CHUNK_OFFSET_WIDTH);
}
static int nth_midxed_pack_entry(struct repository *r,
struct multi_pack_index *m,
struct pack_entry *e,
uint32_t pos)
int fill_midx_entry(struct repository * r,
const struct object_id *oid,
struct pack_entry *e,
struct multi_pack_index *m)
{
uint32_t pos;
uint32_t pack_int_id;
struct packed_git *p;
if (!bsearch_midx(oid, m, &pos))
return 0;
if (pos >= m->num_objects)
return 0;
@ -310,15 +314,9 @@ static int nth_midxed_pack_entry(struct repository *r,
if (!is_pack_valid(p))
return 0;
if (p->num_bad_objects) {
uint32_t i;
struct object_id oid;
nth_midxed_object_oid(&oid, m, pos);
for (i = 0; i < p->num_bad_objects; i++)
if (hasheq(oid.hash,
p->bad_object_sha1 + the_hash_algo->rawsz * i))
return 0;
}
if (oidset_size(&p->bad_objects) &&
oidset_contains(&p->bad_objects, oid))
return 0;
e->offset = nth_midxed_offset(m, pos);
e->p = p;
@ -326,19 +324,6 @@ static int nth_midxed_pack_entry(struct repository *r,
return 1;
}
int fill_midx_entry(struct repository * r,
const struct object_id *oid,
struct pack_entry *e,
struct multi_pack_index *m)
{
uint32_t pos;
if (!bsearch_midx(oid, m, &pos))
return 0;
return nth_midxed_pack_entry(r, m, e, pos);
}
/* Match "foo.idx" against either "foo.pack" _or_ "foo.idx". */
static int cmp_idx_or_pack_name(const char *idx_or_pack_name,
const char *idx_name)

View File

@ -1642,7 +1642,7 @@ static int do_oid_object_info_extended(struct repository *r,
return 0;
rtype = packed_object_info(r, e.p, e.offset, oi);
if (rtype < 0) {
mark_bad_packed_object(e.p, real->hash);
mark_bad_packed_object(e.p, real);
return do_oid_object_info_extended(r, real, oi, 0);
} else if (oi->whence == OI_PACKED) {
oi->u.packed.offset = e.offset;
@ -1751,7 +1751,7 @@ void *read_object_file_extended(struct repository *r,
die(_("loose object %s (stored in %s) is corrupt"),
oid_to_hex(repl), path);
if ((p = has_packed_and_bad(r, repl->hash)) != NULL)
if ((p = has_packed_and_bad(r, repl)) != NULL)
die(_("packed object %s (stored in %s) is corrupt"),
oid_to_hex(repl), p->pack_name);
obj_read_unlock();

View File

@ -10,6 +10,7 @@
#include "khash.h"
#include "dir.h"
#include "oidtree.h"
#include "oidset.h"
struct object_directory {
struct object_directory *next;
@ -76,9 +77,8 @@ struct packed_git {
const void *index_data;
size_t index_size;
uint32_t num_objects;
uint32_t num_bad_objects;
uint32_t crc_offset;
unsigned char *bad_object_sha1;
struct oidset bad_objects;
int index_version;
time_t mtime;
int pack_fd;

View File

@ -36,11 +36,6 @@ void oidset_clear(struct oidset *set)
oidset_init(set, 0);
}
int oidset_size(struct oidset *set)
{
return kh_size(&set->set);
}
void oidset_parse_file(struct oidset *set, const char *path)
{
oidset_parse_file_carefully(set, path, NULL, NULL);

View File

@ -57,7 +57,10 @@ int oidset_remove(struct oidset *set, const struct object_id *oid);
/**
* Returns the number of oids in the set.
*/
int oidset_size(struct oidset *set);
static inline int oidset_size(const struct oidset *set)
{
return kh_size(&set->set);
}
/**
* Remove all entries from the oidset, freeing any resources associated with

View File

@ -109,7 +109,7 @@ off_t pack_pos_to_offset(struct packed_git *p, uint32_t pos);
* If the reverse index has not yet been loaded, or the position is out of
* bounds, this function aborts.
*
* This function runs in time O(log N) with the number of objects in the MIDX.
* This function runs in constant time.
*/
uint32_t pack_pos_to_midx(struct multi_pack_index *m, uint32_t pos);
@ -120,7 +120,7 @@ uint32_t pack_pos_to_midx(struct multi_pack_index *m, uint32_t pos);
* If the reverse index has not yet been loaded, or the position is out of
* bounds, this function aborts.
*
* This function runs in constant time.
* This function runs in time O(log N) with the number of objects in the MIDX.
*/
int midx_to_pack_pos(struct multi_pack_index *midx, uint32_t at, uint32_t *pos);

View File

@ -1161,31 +1161,19 @@ int unpack_object_header(struct packed_git *p,
return type;
}
void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1)
void mark_bad_packed_object(struct packed_git *p, const struct object_id *oid)
{
unsigned i;
const unsigned hashsz = the_hash_algo->rawsz;
for (i = 0; i < p->num_bad_objects; i++)
if (hasheq(sha1, p->bad_object_sha1 + hashsz * i))
return;
p->bad_object_sha1 = xrealloc(p->bad_object_sha1,
st_mult(GIT_MAX_RAWSZ,
st_add(p->num_bad_objects, 1)));
hashcpy(p->bad_object_sha1 + hashsz * p->num_bad_objects, sha1);
p->num_bad_objects++;
oidset_insert(&p->bad_objects, oid);
}
const struct packed_git *has_packed_and_bad(struct repository *r,
const unsigned char *sha1)
const struct object_id *oid)
{
struct packed_git *p;
unsigned i;
for (p = r->objects->packed_git; p; p = p->next)
for (i = 0; i < p->num_bad_objects; i++)
if (hasheq(sha1,
p->bad_object_sha1 + the_hash_algo->rawsz * i))
return p;
if (oidset_contains(&p->bad_objects, oid))
return p;
return NULL;
}
@ -1272,7 +1260,7 @@ static int retry_bad_packed_offset(struct repository *r,
if (offset_to_pack_pos(p, obj_offset, &pos) < 0)
return OBJ_BAD;
nth_packed_object_id(&oid, p, pack_pos_to_index(p, pos));
mark_bad_packed_object(p, oid.hash);
mark_bad_packed_object(p, &oid);
type = oid_object_info(r, &oid, NULL);
if (type <= OBJ_NONE)
return OBJ_BAD;
@ -1722,7 +1710,7 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset,
nth_packed_object_id(&oid, p, index_pos);
error("bad packed object CRC for %s",
oid_to_hex(&oid));
mark_bad_packed_object(p, oid.hash);
mark_bad_packed_object(p, &oid);
data = NULL;
goto out;
}
@ -1811,7 +1799,7 @@ void *unpack_entry(struct repository *r, struct packed_git *p, off_t obj_offset,
" at offset %"PRIuMAX" from %s",
oid_to_hex(&base_oid), (uintmax_t)obj_offset,
p->pack_name);
mark_bad_packed_object(p, base_oid.hash);
mark_bad_packed_object(p, &base_oid);
base = read_object(r, &base_oid, &type, &base_size);
external_base = base;
}
@ -2016,13 +2004,9 @@ static int fill_pack_entry(const struct object_id *oid,
{
off_t offset;
if (p->num_bad_objects) {
unsigned i;
for (i = 0; i < p->num_bad_objects; i++)
if (hasheq(oid->hash,
p->bad_object_sha1 + the_hash_algo->rawsz * i))
return 0;
}
if (oidset_size(&p->bad_objects) &&
oidset_contains(&p->bad_objects, oid))
return 0;
offset = find_pack_entry_one(oid->hash, p);
if (!offset)

View File

@ -159,8 +159,8 @@ int packed_object_info(struct repository *r,
struct packed_git *pack,
off_t offset, struct object_info *);
void mark_bad_packed_object(struct packed_git *p, const unsigned char *sha1);
const struct packed_git *has_packed_and_bad(struct repository *r, const unsigned char *sha1);
void mark_bad_packed_object(struct packed_git *, const struct object_id *);
const struct packed_git *has_packed_and_bad(struct repository *, const struct object_id *);
#define ON_DISK_KEEP_PACKS 1
#define IN_CORE_KEEP_PACKS 2

View File

@ -310,19 +310,6 @@ static enum parse_opt_result parse_long_opt(
again:
if (!skip_prefix(arg, long_name, &rest))
rest = NULL;
if (options->type == OPTION_ARGUMENT) {
if (!rest)
continue;
if (*rest == '=')
return error(_("%s takes no value"),
optname(options, flags));
if (*rest)
continue;
if (options->value)
*(int *)options->value = options->defval;
p->out[p->cpidx++] = arg - 2;
return PARSE_OPT_DONE;
}
if (!rest) {
/* abbreviated? */
if (!(p->flags & PARSE_OPT_KEEP_UNKNOWN) &&

View File

@ -8,7 +8,6 @@
enum parse_opt_type {
/* special types */
OPTION_END,
OPTION_ARGUMENT,
OPTION_GROUP,
OPTION_NUMBER,
OPTION_ALIAS,
@ -155,8 +154,6 @@ struct option {
#define OPT_INTEGER_F(s, l, v, h, f) { OPTION_INTEGER, (s), (l), (v), N_("n"), (h), (f) }
#define OPT_END() { OPTION_END }
#define OPT_ARGUMENT(l, v, h) { OPTION_ARGUMENT, 0, (l), (v), NULL, \
(h), PARSE_OPT_NOARG, NULL, 1 }
#define OPT_GROUP(h) { OPTION_GROUP, 0, NULL, NULL, NULL, (h) }
#define OPT_BIT(s, l, v, h, b) OPT_BIT_F(s, l, v, h, b, 0)
#define OPT_BITOP(s, l, v, h, set, clear) { OPTION_BITOP, (s), (l), (v), NULL, (h), \

View File

@ -2100,8 +2100,7 @@ static int filter_pattern_match(struct ref_filter *filter, const char *refname)
*/
static int for_each_fullref_in_pattern(struct ref_filter *filter,
each_ref_fn cb,
void *cb_data,
int broken)
void *cb_data)
{
if (!filter->match_as_path) {
/*
@ -2109,7 +2108,7 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
* prefixes like "refs/heads/" etc. are stripped off,
* so we have to look at everything:
*/
return for_each_fullref_in("", cb, cb_data, broken);
return for_each_fullref_in("", cb, cb_data);
}
if (filter->ignore_case) {
@ -2118,16 +2117,16 @@ static int for_each_fullref_in_pattern(struct ref_filter *filter,
* so just return everything and let the caller
* sort it out.
*/
return for_each_fullref_in("", cb, cb_data, broken);
return for_each_fullref_in("", cb, cb_data);
}
if (!filter->name_patterns[0]) {
/* no patterns; we have to look at everything */
return for_each_fullref_in("", cb, cb_data, broken);
return for_each_fullref_in("", cb, cb_data);
}
return for_each_fullref_in_prefixes(NULL, filter->name_patterns,
cb, cb_data, broken);
cb, cb_data);
}
/*
@ -2405,13 +2404,10 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
{
struct ref_filter_cbdata ref_cbdata;
int ret = 0;
unsigned int broken = 0;
ref_cbdata.array = array;
ref_cbdata.filter = filter;
if (type & FILTER_REFS_INCLUDE_BROKEN)
broken = 1;
filter->kind = type & FILTER_REFS_KIND_MASK;
init_contains_cache(&ref_cbdata.contains_cache);
@ -2428,13 +2424,13 @@ int filter_refs(struct ref_array *array, struct ref_filter *filter, unsigned int
* of filter_ref_kind().
*/
if (filter->kind == FILTER_REFS_BRANCHES)
ret = for_each_fullref_in("refs/heads/", ref_filter_handler, &ref_cbdata, broken);
ret = for_each_fullref_in("refs/heads/", ref_filter_handler, &ref_cbdata);
else if (filter->kind == FILTER_REFS_REMOTES)
ret = for_each_fullref_in("refs/remotes/", ref_filter_handler, &ref_cbdata, broken);
ret = for_each_fullref_in("refs/remotes/", ref_filter_handler, &ref_cbdata);
else if (filter->kind == FILTER_REFS_TAGS)
ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata, broken);
ret = for_each_fullref_in("refs/tags/", ref_filter_handler, &ref_cbdata);
else if (filter->kind & FILTER_REFS_ALL)
ret = for_each_fullref_in_pattern(filter, ref_filter_handler, &ref_cbdata, broken);
ret = for_each_fullref_in_pattern(filter, ref_filter_handler, &ref_cbdata);
if (!ret && (filter->kind & FILTER_REFS_DETACHED_HEAD))
head_ref(ref_filter_handler, &ref_cbdata);
}

View File

@ -13,7 +13,6 @@
#define QUOTE_PYTHON 4
#define QUOTE_TCL 8
#define FILTER_REFS_INCLUDE_BROKEN 0x0001
#define FILTER_REFS_TAGS 0x0002
#define FILTER_REFS_BRANCHES 0x0004
#define FILTER_REFS_REMOTES 0x0008

42
refs.c
View File

@ -1413,14 +1413,21 @@ int head_ref(each_ref_fn fn, void *cb_data)
struct ref_iterator *refs_ref_iterator_begin(
struct ref_store *refs,
const char *prefix, int trim, int flags)
const char *prefix, int trim,
enum do_for_each_ref_flags flags)
{
struct ref_iterator *iter;
if (ref_paranoia < 0)
ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 0);
if (ref_paranoia)
flags |= DO_FOR_EACH_INCLUDE_BROKEN;
if (!(flags & DO_FOR_EACH_INCLUDE_BROKEN)) {
static int ref_paranoia = -1;
if (ref_paranoia < 0)
ref_paranoia = git_env_bool("GIT_REF_PARANOIA", 1);
if (ref_paranoia) {
flags |= DO_FOR_EACH_INCLUDE_BROKEN;
flags |= DO_FOR_EACH_OMIT_DANGLING_SYMREFS;
}
}
iter = refs->be->iterator_begin(refs, prefix, flags);
@ -1479,7 +1486,8 @@ static int do_for_each_ref_helper(struct repository *r,
}
static int do_for_each_ref(struct ref_store *refs, const char *prefix,
each_ref_fn fn, int trim, int flags, void *cb_data)
each_ref_fn fn, int trim,
enum do_for_each_ref_flags flags, void *cb_data)
{
struct ref_iterator *iter;
struct do_for_each_ref_help hp = { fn, cb_data };
@ -1514,25 +1522,16 @@ int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data)
return refs_for_each_ref_in(get_main_ref_store(the_repository), prefix, fn, cb_data);
}
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data, unsigned int broken)
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data)
{
unsigned int flag = 0;
if (broken)
flag = DO_FOR_EACH_INCLUDE_BROKEN;
return do_for_each_ref(get_main_ref_store(the_repository),
prefix, fn, 0, flag, cb_data);
prefix, fn, 0, 0, cb_data);
}
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
each_ref_fn fn, void *cb_data,
unsigned int broken)
each_ref_fn fn, void *cb_data)
{
unsigned int flag = 0;
if (broken)
flag = DO_FOR_EACH_INCLUDE_BROKEN;
return do_for_each_ref(refs, prefix, fn, 0, flag, cb_data);
return do_for_each_ref(refs, prefix, fn, 0, 0, cb_data);
}
int for_each_replace_ref(struct repository *r, each_repo_ref_fn fn, void *cb_data)
@ -1624,8 +1623,7 @@ static void find_longest_prefixes(struct string_list *out,
int for_each_fullref_in_prefixes(const char *namespace,
const char **patterns,
each_ref_fn fn, void *cb_data,
unsigned int broken)
each_ref_fn fn, void *cb_data)
{
struct string_list prefixes = STRING_LIST_INIT_DUP;
struct string_list_item *prefix;
@ -1640,7 +1638,7 @@ int for_each_fullref_in_prefixes(const char *namespace,
for_each_string_list_item(prefix, &prefixes) {
strbuf_addstr(&buf, prefix->string);
ret = for_each_fullref_in(buf.buf, fn, cb_data, broken);
ret = for_each_fullref_in(buf.buf, fn, cb_data);
if (ret)
break;
strbuf_setlen(&buf, namespace_len);

9
refs.h
View File

@ -342,10 +342,8 @@ int for_each_ref(each_ref_fn fn, void *cb_data);
int for_each_ref_in(const char *prefix, each_ref_fn fn, void *cb_data);
int refs_for_each_fullref_in(struct ref_store *refs, const char *prefix,
each_ref_fn fn, void *cb_data,
unsigned int broken);
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
unsigned int broken);
each_ref_fn fn, void *cb_data);
int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data);
/**
* iterate all refs in "patterns" by partitioning patterns into disjoint sets
@ -354,8 +352,7 @@ int for_each_fullref_in(const char *prefix, each_ref_fn fn, void *cb_data,
* callers should be prepared to ignore references that they did not ask for.
*/
int for_each_fullref_in_prefixes(const char *namespace, const char **patterns,
each_ref_fn fn, void *cb_data,
unsigned int broken);
each_ref_fn fn, void *cb_data);
/**
* iterate refs from the respective area.
*/

View File

@ -744,6 +744,11 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
ref_type(iter->iter0->refname) != REF_TYPE_PER_WORKTREE)
continue;
if ((iter->flags & DO_FOR_EACH_OMIT_DANGLING_SYMREFS) &&
(iter->iter0->flags & REF_ISSYMREF) &&
(iter->iter0->flags & REF_ISBROKEN))
continue;
if (!(iter->flags & DO_FOR_EACH_INCLUDE_BROKEN) &&
!ref_resolves_to_object(iter->iter0->refname,
iter->iter0->oid,

View File

@ -245,8 +245,36 @@ int refs_rename_ref_available(struct ref_store *refs,
/* We allow "recursive" symbolic refs. Only within reason, though */
#define SYMREF_MAXDEPTH 5
/* Include broken references in a do_for_each_ref*() iteration: */
#define DO_FOR_EACH_INCLUDE_BROKEN 0x01
/*
* These flags are passed to refs_ref_iterator_begin() (and do_for_each_ref(),
* which feeds it).
*/
enum do_for_each_ref_flags {
/*
* Include broken references in a do_for_each_ref*() iteration, which
* would normally be omitted. This includes both refs that point to
* missing objects (a true repository corruption), ones with illegal
* names (which we prefer not to expose to callers), as well as
* dangling symbolic refs (i.e., those that point to a non-existent
* ref; this is not a corruption, but as they have no valid oid, we
* omit them from normal iteration results).
*/
DO_FOR_EACH_INCLUDE_BROKEN = (1 << 0),
/*
* Only include per-worktree refs in a do_for_each_ref*() iteration.
* Normally this will be used with a files ref_store, since that's
* where all reference backends will presumably store their
* per-worktree refs.
*/
DO_FOR_EACH_PER_WORKTREE_ONLY = (1 << 1),
/*
* Omit dangling symrefs from output; this only has an effect with
* INCLUDE_BROKEN, since they are otherwise not included at all.
*/
DO_FOR_EACH_OMIT_DANGLING_SYMREFS = (1 << 2),
};
/*
* Reference iterators
@ -349,16 +377,12 @@ int is_empty_ref_iterator(struct ref_iterator *ref_iterator);
* Return an iterator that goes over each reference in `refs` for
* which the refname begins with prefix. If trim is non-zero, then
* trim that many characters off the beginning of each refname.
* The output is ordered by refname. The following flags are supported:
*
* DO_FOR_EACH_INCLUDE_BROKEN: include broken references in
* the iteration.
*
* DO_FOR_EACH_PER_WORKTREE_ONLY: only produce REF_TYPE_PER_WORKTREE refs.
* The output is ordered by refname.
*/
struct ref_iterator *refs_ref_iterator_begin(
struct ref_store *refs,
const char *prefix, int trim, int flags);
const char *prefix, int trim,
enum do_for_each_ref_flags flags);
/*
* A callback function used to instruct merge_ref_iterator how to
@ -446,10 +470,8 @@ void base_ref_iterator_free(struct ref_iterator *iter);
/*
* backend-specific implementation of ref_iterator_advance. For symrefs, the
* function should set REF_ISSYMREF, and it should also dereference the symref
* to provide the OID referent. If DO_FOR_EACH_INCLUDE_BROKEN is set, symrefs
* with non-existent referents and refs pointing to non-existent object names
* should also be returned. If DO_FOR_EACH_PER_WORKTREE_ONLY, only
* REF_TYPE_PER_WORKTREE refs should be returned.
* to provide the OID referent. It should respect do_for_each_ref_flags
* that were passed to refs_ref_iterator_begin().
*/
typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator);
@ -498,14 +520,6 @@ int do_for_each_repo_ref_iterator(struct repository *r,
struct ref_iterator *iter,
each_repo_ref_fn fn, void *cb_data);
/*
* Only include per-worktree refs in a do_for_each_ref*() iteration.
* Normally this will be used with a files ref_store, since that's
* where all reference backends will presumably store their
* per-worktree refs.
*/
#define DO_FOR_EACH_PER_WORKTREE_ONLY 0x02
struct ref_store;
/* refs backends */

View File

@ -216,8 +216,7 @@ int repo_submodule_init(struct repository *subrepo,
}
strbuf_reset(&gitdir);
strbuf_repo_git_path(&gitdir, superproject,
"modules/%s", sub->name);
submodule_name_to_gitdir(&gitdir, superproject, sub->name);
if (repo_init(subrepo, gitdir.buf, NULL)) {
ret = -1;

View File

@ -2548,7 +2548,7 @@ static int for_each_bisect_ref(struct ref_store *refs, each_ref_fn fn,
struct strbuf bisect_refs = STRBUF_INIT;
int status;
strbuf_addf(&bisect_refs, "refs/bisect/%s", term);
status = refs_for_each_fullref_in(refs, bisect_refs.buf, fn, cb_data, 0);
status = refs_for_each_fullref_in(refs, bisect_refs.buf, fn, cb_data);
strbuf_release(&bisect_refs);
return status;
}

View File

@ -211,9 +211,9 @@ static char *locate_in_PATH(const char *file)
return NULL;
}
static int exists_in_PATH(const char *file)
int exists_in_PATH(const char *command)
{
char *r = locate_in_PATH(file);
char *r = locate_in_PATH(command);
int found = r != NULL;
free(r);
return found;

View File

@ -190,6 +190,18 @@ void child_process_clear(struct child_process *);
int is_executable(const char *name);
/**
* Check if the command exists on $PATH. This emulates the path search that
* execvp would perform, without actually executing the command so it
* can be used before fork() to prepare to run a command using
* execve() or after execvp() to diagnose why it failed.
*
* The caller should ensure that command contains no directory separators.
*
* Returns 1 if it is found in $PATH or 0 if the command could not be found.
*/
int exists_in_PATH(const char *command);
/**
* Start a sub-process. Takes a pointer to a `struct child_process`
* that specifies the details and returns pipe FDs (if requested).

View File

@ -29,8 +29,8 @@ extern const char *empty_strvec[];
*/
struct strvec {
const char **v;
int nr;
int alloc;
size_t nr;
size_t alloc;
};
#define STRVEC_INIT { empty_strvec, 0, 0 }

View File

@ -1845,14 +1845,16 @@ int bad_to_remove_submodule(const char *path, unsigned flags)
void submodule_unset_core_worktree(const struct submodule *sub)
{
char *config_path = xstrfmt("%s/modules/%s/config",
get_git_dir(), sub->name);
struct strbuf config_path = STRBUF_INIT;
if (git_config_set_in_file_gently(config_path, "core.worktree", NULL))
submodule_name_to_gitdir(&config_path, the_repository, sub->name);
strbuf_addstr(&config_path, "/config");
if (git_config_set_in_file_gently(config_path.buf, "core.worktree", NULL))
warning(_("Could not unset core.worktree setting in submodule '%s'"),
sub->path);
free(config_path);
strbuf_release(&config_path);
}
static const char *get_super_prefix_or_empty(void)
@ -1948,20 +1950,22 @@ int submodule_move_head(const char *path,
absorb_git_dir_into_superproject(path,
ABSORB_GITDIR_RECURSE_SUBMODULES);
} else {
char *gitdir = xstrfmt("%s/modules/%s",
get_git_dir(), sub->name);
connect_work_tree_and_git_dir(path, gitdir, 0);
free(gitdir);
struct strbuf gitdir = STRBUF_INIT;
submodule_name_to_gitdir(&gitdir, the_repository,
sub->name);
connect_work_tree_and_git_dir(path, gitdir.buf, 0);
strbuf_release(&gitdir);
/* make sure the index is clean as well */
submodule_reset_index(path);
}
if (old_head && (flags & SUBMODULE_MOVE_HEAD_FORCE)) {
char *gitdir = xstrfmt("%s/modules/%s",
get_git_dir(), sub->name);
connect_work_tree_and_git_dir(path, gitdir, 1);
free(gitdir);
struct strbuf gitdir = STRBUF_INIT;
submodule_name_to_gitdir(&gitdir, the_repository,
sub->name);
connect_work_tree_and_git_dir(path, gitdir.buf, 1);
strbuf_release(&gitdir);
}
}
@ -2076,7 +2080,7 @@ int validate_submodule_git_dir(char *git_dir, const char *submodule_name)
static void relocate_single_git_dir_into_superproject(const char *path)
{
char *old_git_dir = NULL, *real_old_git_dir = NULL, *real_new_git_dir = NULL;
char *new_git_dir;
struct strbuf new_gitdir = STRBUF_INIT;
const struct submodule *sub;
if (submodule_uses_worktrees(path))
@ -2094,14 +2098,13 @@ static void relocate_single_git_dir_into_superproject(const char *path)
if (!sub)
die(_("could not lookup name for submodule '%s'"), path);
new_git_dir = git_pathdup("modules/%s", sub->name);
if (validate_submodule_git_dir(new_git_dir, sub->name) < 0)
submodule_name_to_gitdir(&new_gitdir, the_repository, sub->name);
if (validate_submodule_git_dir(new_gitdir.buf, sub->name) < 0)
die(_("refusing to move '%s' into an existing git dir"),
real_old_git_dir);
if (safe_create_leading_directories_const(new_git_dir) < 0)
die(_("could not create directory '%s'"), new_git_dir);
real_new_git_dir = real_pathdup(new_git_dir, 1);
free(new_git_dir);
if (safe_create_leading_directories_const(new_gitdir.buf) < 0)
die(_("could not create directory '%s'"), new_gitdir.buf);
real_new_git_dir = real_pathdup(new_gitdir.buf, 1);
fprintf(stderr, _("Migrating git directory of '%s%s' from\n'%s' to\n'%s'\n"),
get_super_prefix_or_empty(), path,
@ -2112,6 +2115,7 @@ static void relocate_single_git_dir_into_superproject(const char *path)
free(old_git_dir);
free(real_old_git_dir);
free(real_new_git_dir);
strbuf_release(&new_gitdir);
}
/*
@ -2131,6 +2135,7 @@ void absorb_git_dir_into_superproject(const char *path,
/* Not populated? */
if (!sub_git_dir) {
const struct submodule *sub;
struct strbuf sub_gitdir = STRBUF_INIT;
if (err_code == READ_GITFILE_ERR_STAT_FAILED) {
/* unpopulated as expected */
@ -2152,8 +2157,9 @@ void absorb_git_dir_into_superproject(const char *path,
sub = submodule_from_path(the_repository, null_oid(), path);
if (!sub)
die(_("could not lookup name for submodule '%s'"), path);
connect_work_tree_and_git_dir(path,
git_path("modules/%s", sub->name), 0);
submodule_name_to_gitdir(&sub_gitdir, the_repository, sub->name);
connect_work_tree_and_git_dir(path, sub_gitdir.buf, 0);
strbuf_release(&sub_gitdir);
} else {
/* Is it already absorbed into the superprojects git dir? */
char *real_sub_git_dir = real_pathdup(sub_git_dir, 1);
@ -2304,9 +2310,36 @@ int submodule_to_gitdir(struct strbuf *buf, const char *submodule)
goto cleanup;
}
strbuf_reset(buf);
strbuf_git_path(buf, "%s/%s", "modules", sub->name);
submodule_name_to_gitdir(buf, the_repository, sub->name);
}
cleanup:
return ret;
}
void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
const char *submodule_name)
{
/*
* NEEDSWORK: The current way of mapping a submodule's name to
* its location in .git/modules/ has problems with some naming
* schemes. For example, if a submodule is named "foo" and
* another is named "foo/bar" (whether present in the same
* superproject commit or not - the problem will arise if both
* superproject commits have been checked out at any point in
* time), or if two submodule names only have different cases in
* a case-insensitive filesystem.
*
* There are several solutions, including encoding the path in
* some way, introducing a submodule.<name>.gitdir config in
* .git/config (not .gitmodules) that allows overriding what the
* gitdir of a submodule would be (and teach Git, upon noticing
* a clash, to automatically determine a non-clashing name and
* to write such a config), or introducing a
* submodule.<name>.gitdir config in .gitmodules that repo
* administrators can explicitly set. Nothing has been decided,
* so for now, just append the name at the end of the path.
*/
strbuf_repo_git_path(buf, r, "modules/");
strbuf_addstr(buf, submodule_name);
}

View File

@ -132,6 +132,13 @@ int push_unpushed_submodules(struct repository *r,
*/
int submodule_to_gitdir(struct strbuf *buf, const char *submodule);
/*
* Given a submodule name, create a path to where the submodule's gitdir lives
* inside of the provided repository's 'modules' directory.
*/
void submodule_name_to_gitdir(struct strbuf *buf, struct repository *r,
const char *submodule_name);
/*
* Make sure that no submodule's git dir is nested in a sibling submodule's.
*/

View File

@ -134,7 +134,6 @@ int cmd__parse_options(int argc, const char **argv)
OPT_NOOP_NOARG(0, "obsolete"),
OPT_STRING_LIST(0, "list", &list, "str", "add str to list"),
OPT_GROUP("Magic arguments"),
OPT_ARGUMENT("quux", NULL, "means --quux"),
OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
number_callback),
{ OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b",

View File

@ -61,7 +61,7 @@ struct testsuite {
int quiet, immediate, verbose, verbose_log, trace, write_junit_xml;
};
#define TESTSUITE_INIT \
{ STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, -1, 0, 0, 0, 0, 0, 0 }
{ STRING_LIST_INIT_DUP, STRING_LIST_INIT_DUP, 0, 0, 0, 0, 0, 0, 0 }
static int next_test(struct child_process *cp, struct strbuf *err, void *cb,
void **task_cb)
@ -142,9 +142,6 @@ static int testsuite(int argc, const char **argv)
OPT_END()
};
memset(&suite, 0, sizeof(suite));
suite.tests.strdup_strings = suite.failed.strdup_strings = 1;
argc = parse_options(argc, argv, NULL, options,
testsuite_usage, PARSE_OPT_STOP_AT_NON_OPTION);

View File

@ -81,8 +81,6 @@ PassEnv GIT_TRACE
PassEnv GIT_CONFIG_NOSYSTEM
PassEnv GIT_TEST_SIDEBAND_ALL
SetEnvIf Git-Protocol ".*" GIT_PROTOCOL=$0
Alias /dumb/ www/
Alias /auth/dumb/ www/auth/dumb/
@ -117,6 +115,11 @@ Alias /auth/dumb/ www/auth/dumb/
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
SetEnv GIT_HTTP_EXPORT_ALL
</LocationMatch>
<LocationMatch /smart_v0/>
SetEnv GIT_EXEC_PATH ${GIT_EXEC_PATH}
SetEnv GIT_HTTP_EXPORT_ALL
SetEnv GIT_PROTOCOL
</LocationMatch>
ScriptAlias /smart/incomplete_length/git-upload-pack incomplete-length-upload-pack-v2-http.sh/
ScriptAlias /smart/incomplete_body/git-upload-pack incomplete-body-upload-pack-v2-http.sh/
ScriptAliasMatch /error_git_upload_pack/(.*)/git-upload-pack error.sh/

View File

@ -1271,28 +1271,29 @@ P=$(test_oid root)
test_expect_success 'git commit-tree records the correct tree in a commit' '
commit0=$(echo NO | git commit-tree $P) &&
tree=$(git show --pretty=raw $commit0 |
sed -n -e "s/^tree //p" -e "/^author /q") &&
git show --pretty=raw $commit0 >out &&
tree=$(sed -n -e "s/^tree //p" -e "/^author /q" out) &&
test "z$tree" = "z$P"
'
test_expect_success 'git commit-tree records the correct parent in a commit' '
commit1=$(echo NO | git commit-tree $P -p $commit0) &&
parent=$(git show --pretty=raw $commit1 |
sed -n -e "s/^parent //p" -e "/^author /q") &&
git show --pretty=raw $commit1 >out &&
parent=$(sed -n -e "s/^parent //p" -e "/^author /q" out) &&
test "z$commit0" = "z$parent"
'
test_expect_success 'git commit-tree omits duplicated parent in a commit' '
commit2=$(echo NO | git commit-tree $P -p $commit0 -p $commit0) &&
parent=$(git show --pretty=raw $commit2 |
sed -n -e "s/^parent //p" -e "/^author /q" |
sort -u) &&
git show --pretty=raw $commit2 >out &&
cat >match.sed <<-\EOF &&
s/^parent //p
/^author /q
EOF
parent=$(sed -n -f match.sed out | sort -u) &&
test "z$commit0" = "z$parent" &&
numparent=$(git show --pretty=raw $commit2 |
sed -n -e "s/^parent //p" -e "/^author /q" |
wc -l) &&
test $numparent = 1
git show --pretty=raw $commit2 >out &&
test_stdout_line_count = 1 sed -n -f match.sed out
'
test_expect_success 'update-index D/F conflict' '

View File

@ -73,6 +73,22 @@ test_expect_success 'git help -g' '
test_i18ngrep "^ tutorial " help.output
'
test_expect_success 'git help fails for non-existing html pages' '
configure_help &&
mkdir html-empty &&
test_must_fail git -c help.htmlpath=html-empty help status &&
test_must_be_empty test-browser.log
'
test_expect_success 'git help succeeds without git.html' '
configure_help &&
mkdir html-with-docs &&
touch html-with-docs/git-status.html &&
git -c help.htmlpath=html-with-docs help status &&
echo "html-with-docs/git-status.html" >expect &&
test_cmp expect test-browser.log
'
test_expect_success 'generate builtin list' '
git --list-cmds=builtins >builtins
'

View File

@ -37,7 +37,6 @@ String options
--list <str> add str to list
Magic arguments
--quux means --quux
-NUM set integer to NUM
+ same as -b
--ambiguous positive ambiguity
@ -263,10 +262,6 @@ test_expect_success 'detect possible typos' '
test_cmp typo.err output.err
'
test_expect_success 'keep some options as arguments' '
test-tool parse-options --expect="arg 00: --quux" --quux
'
cat >expect <<\EOF
Callback: "four", 0
boolean: 5

View File

@ -195,6 +195,7 @@ test_expect_success 'reset --hard gives cache-tree' '
test_expect_success 'reset --hard without index gives cache-tree' '
rm -f .git/index &&
git clean -fd &&
git reset --hard &&
test_cache_tree
'

View File

@ -9,6 +9,21 @@ test -z "$NO_UNIX_SOCKETS" || {
test_done
}
uname_s=$(uname -s)
case $uname_s in
*MINGW*)
test_path_is_socket () {
# `test -S` cannot detect Win10's Unix sockets
test_path_exists "$1"
}
;;
*)
test_path_is_socket () {
test -S "$1"
}
;;
esac
# don't leave a stale daemon running
test_atexit 'git credential-cache exit'
@ -21,7 +36,7 @@ test_expect_success 'socket defaults to ~/.cache/git/credential/socket' '
rmdir -p .cache/git/credential/
" &&
test_path_is_missing "$HOME/.git-credential-cache" &&
test -S "$HOME/.cache/git/credential/socket"
test_path_is_socket "$HOME/.cache/git/credential/socket"
'
XDG_CACHE_HOME="$HOME/xdg"
@ -31,7 +46,7 @@ helper_test cache
test_expect_success "use custom XDG_CACHE_HOME if set and default sockets are not created" '
test_when_finished "git credential-cache exit" &&
test -S "$XDG_CACHE_HOME/git/credential/socket" &&
test_path_is_socket "$XDG_CACHE_HOME/git/credential/socket" &&
test_path_is_missing "$HOME/.git-credential-cache/socket" &&
test_path_is_missing "$HOME/.cache/git/credential/socket"
'
@ -48,7 +63,7 @@ test_expect_success 'credential-cache --socket option overrides default location
username=store-user
password=store-pass
EOF
test -S "$HOME/dir/socket"
test_path_is_socket "$HOME/dir/socket"
'
test_expect_success "use custom XDG_CACHE_HOME even if xdg socket exists" '
@ -62,7 +77,7 @@ test_expect_success "use custom XDG_CACHE_HOME even if xdg socket exists" '
username=store-user
password=store-pass
EOF
test -S "$HOME/.cache/git/credential/socket" &&
test_path_is_socket "$HOME/.cache/git/credential/socket" &&
XDG_CACHE_HOME="$HOME/xdg" &&
export XDG_CACHE_HOME &&
check approve cache <<-\EOF &&
@ -71,7 +86,7 @@ test_expect_success "use custom XDG_CACHE_HOME even if xdg socket exists" '
username=store-user
password=store-pass
EOF
test -S "$XDG_CACHE_HOME/git/credential/socket"
test_path_is_socket "$XDG_CACHE_HOME/git/credential/socket"
'
test_expect_success 'use user socket if user directory exists' '
@ -79,14 +94,15 @@ test_expect_success 'use user socket if user directory exists' '
git credential-cache exit &&
rmdir \"\$HOME/.git-credential-cache/\"
" &&
mkdir -p -m 700 "$HOME/.git-credential-cache/" &&
mkdir -p "$HOME/.git-credential-cache/" &&
chmod 700 "$HOME/.git-credential-cache/" &&
check approve cache <<-\EOF &&
protocol=https
host=example.com
username=store-user
password=store-pass
EOF
test -S "$HOME/.git-credential-cache/socket"
test_path_is_socket "$HOME/.git-credential-cache/socket"
'
test_expect_success SYMLINKS 'use user socket if user directory is a symlink to a directory' '
@ -103,7 +119,7 @@ test_expect_success SYMLINKS 'use user socket if user directory is a symlink to
username=store-user
password=store-pass
EOF
test -S "$HOME/.git-credential-cache/socket"
test_path_is_socket "$HOME/.git-credential-cache/socket"
'
helper_test_timeout cache --timeout=1

View File

@ -1598,6 +1598,40 @@ test_expect_success 'transaction cannot restart ongoing transaction' '
test_must_fail git show-ref --verify refs/heads/restart
'
test_expect_success PIPE 'transaction flushes status updates' '
mkfifo in out &&
(git update-ref --stdin <in >out &) &&
exec 9>in &&
exec 8<out &&
test_when_finished "exec 9>&-" &&
test_when_finished "exec 8<&-" &&
echo "start" >&9 &&
echo "start: ok" >expected &&
read line <&8 &&
echo "$line" >actual &&
test_cmp expected actual &&
echo "create refs/heads/flush $A" >&9 &&
echo prepare >&9 &&
echo "prepare: ok" >expected &&
read line <&8 &&
echo "$line" >actual &&
test_cmp expected actual &&
# This must now fail given that we have locked the ref.
test_must_fail git update-ref refs/heads/flush $B 2>stderr &&
grep "fatal: update_ref failed for ref ${SQ}refs/heads/flush${SQ}: cannot lock ref" stderr &&
echo commit >&9 &&
echo "commit: ok" >expected &&
read line <&8 &&
echo "$line" >actual &&
test_cmp expected actual
'
test_expect_success 'directory not created deleting packed ref' '
git branch d1/d2/r1 HEAD &&
git pack-refs --all &&

View File

@ -170,7 +170,7 @@ test_expect_success 'for-each-ref emits warnings for broken names' '
! grep -e "badname" output &&
! grep -e "broken\.\.\.symref" output &&
test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.ref" error &&
test_i18ngrep "ignoring broken ref refs/heads/badname" error &&
test_i18ngrep ! "ignoring broken ref refs/heads/badname" error &&
test_i18ngrep "ignoring ref with broken name refs/heads/broken\.\.\.symref" error
'

View File

@ -48,6 +48,7 @@ test_expect_success 'checkout commit with dir must not remove untracked a/b' '
test_expect_success SYMLINKS 'the symlink remained' '
test_when_finished "rm a/b" &&
test -h a/b
'

View File

@ -297,6 +297,7 @@ test_expect_success 'abort with error when new base cannot be checked out' '
output &&
test_i18ngrep "file1" output &&
test_path_is_missing .git/rebase-merge &&
rm file1 &&
git reset --hard HEAD^
'

View File

@ -65,6 +65,7 @@ test_rebase_gpg_sign ! true -i --gpg-sign --no-gpg-sign
test_rebase_gpg_sign false -i --no-gpg-sign --gpg-sign
test_expect_failure 'rebase -p --no-gpg-sign override commit.gpgsign' '
test_when_finished "git clean -f" &&
git reset --hard merged &&
git config commit.gpgsign true &&
git rebase -p --no-gpg-sign --onto=one fork-point main &&

View File

@ -238,6 +238,7 @@ test_expect_success 'allow skipping commit but not abort for a new history' '
'
test_expect_success 'allow skipping stopped cherry-pick because of untracked file modifications' '
test_when_finished "rm unrelated" &&
pristine_detach initial &&
git rm --cached unrelated &&
git commit -m "untrack unrelated" &&

View File

@ -23,7 +23,13 @@ test_expect_success setup '
test_tick &&
git commit -a -m $i || return 1
done &&
git branch changes &&
git format-patch --no-numbered initial &&
git checkout -b conflicting initial &&
echo different >>file-1 &&
echo whatever >new-file &&
git add file-1 new-file &&
git commit -m different &&
git checkout -b side initial &&
echo local change >file-2-expect
'
@ -191,4 +197,37 @@ test_expect_success 'am --abort leaves index stat info alone' '
git diff-files --exit-code --quiet
'
test_expect_success 'git am --abort return failed exit status when it fails' '
test_when_finished "rm -rf file-2/ && git reset --hard && git am --abort" &&
git checkout changes &&
git format-patch -1 --stdout conflicting >changes.mbox &&
test_must_fail git am --3way changes.mbox &&
git rm file-2 &&
mkdir file-2 &&
echo precious >file-2/somefile &&
test_must_fail git am --abort &&
test_path_is_dir file-2/
'
test_expect_success 'git am --abort cleans relevant files' '
git checkout changes &&
git format-patch -1 --stdout conflicting >changes.mbox &&
test_must_fail git am --3way changes.mbox &&
test_path_is_file new-file &&
echo further changes >>file-1 &&
echo change other file >>file-2 &&
# Abort, and expect the files touched by am to be reverted
git am --abort &&
test_path_is_missing new-file &&
# Files not involved in am operation are left modified
git diff --name-only changes >actual &&
test_write_lines file-2 >expect &&
test_cmp expect actual
'
test_done

View File

@ -291,6 +291,7 @@ test_expect_success 'prune: handle HEAD reflog in multiple worktrees' '
cat ../expected >blob &&
git add blob &&
git commit -m "second commit in third" &&
git clean -f && # Remove untracked left behind by deleting index
git reset --hard HEAD^
) &&
git prune --expire=now &&

View File

@ -7,6 +7,9 @@ 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.
Note that we do assert command failure in these cases, because that is
what currently happens. If that changes, these tests should be revisited.
'
GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
@ -18,39 +21,58 @@ test_expect_success 'disable reflogs' '
git reflog expire --expire=all --all
'
create_bogus_ref () {
test_when_finished 'rm -f .git/refs/heads/bogus..name' &&
echo $bogus >.git/refs/heads/bogus..name
}
test_expect_success 'create history reachable only from a bogus-named ref' '
test_tick && git commit --allow-empty -m main &&
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
create_bogus_ref &&
test_must_fail git prune --expire=now &&
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
git cat-file -e $bogus
'
test_expect_success 'non-destructive repack bails on bogus ref' '
create_bogus_ref &&
test_must_fail git repack -adk
'
test_expect_success 'GIT_REF_PARANOIA=0 overrides safety' '
create_bogus_ref &&
GIT_REF_PARANOIA=0 git repack -adk
'
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
create_bogus_ref &&
test_must_fail git repack -Ad --unpack-unreachable=now &&
git cat-file -e $bogus &&
test_must_fail git repack -ad &&
git cat-file -e $bogus
'
# subsequent tests will have different corruptions
test_expect_success 'clean up bogus ref' '
rm .git/refs/heads/bogus..name
test_expect_success 'destructive repack not confused by dangling symref' '
test_when_finished "git symbolic-ref -d refs/heads/dangling" &&
git symbolic-ref refs/heads/dangling refs/heads/does-not-exist &&
git repack -ad &&
test_must_fail git cat-file -e $bogus
'
# We create two new objects here, "one" and "two". Our
@ -77,8 +99,8 @@ test_expect_success 'create history with missing tip commit' '
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_must_fail git prune --expire=now &&
git cat-file -e $recoverable
'
test_expect_success 'pack-refs does not silently delete broken loose ref' '

View File

@ -662,10 +662,10 @@ test_expect_success 'push does not update local refs on failure' '
test_expect_success 'allow deleting an invalid remote ref' '
mk_test testrepo heads/main &&
mk_test testrepo heads/branch &&
rm -f testrepo/.git/objects/??/* &&
git push testrepo :refs/heads/main &&
(cd testrepo && test_must_fail git rev-parse --verify refs/heads/main)
git push testrepo :refs/heads/branch &&
(cd testrepo && test_must_fail git rev-parse --verify refs/heads/branch)
'
@ -706,25 +706,26 @@ test_expect_success 'pushing valid refs triggers post-receive and post-update ho
'
test_expect_success 'deleting dangling ref triggers hooks with correct args' '
mk_test_with_hooks testrepo heads/main &&
mk_test_with_hooks testrepo heads/branch &&
orig=$(git -C testrepo rev-parse refs/heads/branch) &&
rm -f testrepo/.git/objects/??/* &&
git push testrepo :refs/heads/main &&
git push testrepo :refs/heads/branch &&
(
cd testrepo/.git &&
cat >pre-receive.expect <<-EOF &&
$ZERO_OID $ZERO_OID refs/heads/main
$orig $ZERO_OID refs/heads/branch
EOF
cat >update.expect <<-EOF &&
refs/heads/main $ZERO_OID $ZERO_OID
refs/heads/branch $orig $ZERO_OID
EOF
cat >post-receive.expect <<-EOF &&
$ZERO_OID $ZERO_OID refs/heads/main
$orig $ZERO_OID refs/heads/branch
EOF
cat >post-update.expect <<-EOF &&
refs/heads/main
refs/heads/branch
EOF
test_cmp pre-receive.expect pre-receive.actual &&

View File

@ -558,4 +558,13 @@ test_expect_success 'http auth forgets bogus credentials' '
expect_askpass both user@host
'
test_expect_success 'client falls back from v2 to v0 to match server' '
GIT_TRACE_PACKET=$PWD/trace \
GIT_TEST_PROTOCOL_VERSION=2 \
git clone $HTTPD_URL/smart_v0/repo.git repo-v0 &&
# check for v0; there the HEAD symref is communicated in the capability
# line; v2 uses a different syntax on each ref advertisement line
grep symref=HEAD:refs/heads/ trace
'
test_done

View File

@ -35,7 +35,9 @@ test_expect_success 'create a repo to clone' '
'
test_expect_success 'create objects in repo for later corruption' '
test_commit -C foo file
test_commit -C foo file &&
git -C foo checkout --detach &&
test_commit -C foo detached
'
# source repository given to git clone should be relative to the

View File

@ -962,4 +962,22 @@ test_expect_success 'bisect handles annotated tags' '
grep "$bad is the first bad commit" output
'
test_expect_success 'bisect run fails with exit code equals or greater than 128' '
write_script test_script.sh <<-\EOF &&
exit 128
EOF
test_must_fail git bisect run ./test_script.sh &&
write_script test_script.sh <<-\EOF &&
exit 255
EOF
test_must_fail git bisect run ./test_script.sh
'
test_expect_success 'bisect visualize with a filename with dash and space' '
echo "My test line" >>"./-hello 2" &&
git add -- "./-hello 2" &&
git commit --quiet -m "Add test line" -- "./-hello 2" &&
git bisect visualize -p -- "-hello 2"
'
test_done

View File

@ -25,7 +25,8 @@ test_expect_success 'checkout does not clobber untracked symlink' '
git reset --hard main &&
git rm --cached a/b &&
git commit -m "untracked symlink remains" &&
test_must_fail git checkout start^0
test_must_fail git checkout start^0 &&
git clean -fd # Do not leave the untracked symlink in the way
'
test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' '
@ -34,7 +35,8 @@ test_expect_success 'a/b-2/c/d is kept when clobbering symlink b' '
git rm --cached a/b &&
git commit -m "untracked symlink remains" &&
git checkout -f start^0 &&
test_path_is_file a/b-2/c/d
test_path_is_file a/b-2/c/d &&
git clean -fd # Do not leave the untracked symlink in the way
'
test_expect_success 'checkout should not have deleted a/b-2/c/d' '

View File

@ -132,6 +132,7 @@ test_expect_success 'merge-recursive, when index==head but head!=HEAD' '
# Make index match B
git diff C B -- | git apply --cached &&
test_when_finished "git clean -fd" && # Do not leave untracked around
# Merge B & F, with B as "head"
git merge-recursive A -- B F > out &&
test_i18ngrep "Already up to date" out

View File

@ -718,7 +718,9 @@ test_expect_success 'merge-recursive remembers the names of all base trees' '
# merge-recursive prints in reverse order, but we do not care
sort <trees >expect &&
sed -n "s/^virtual //p" out | sort >actual &&
test_cmp expect actual
test_cmp expect actual &&
git clean -fd
'
test_expect_success 'merge-recursive internal merge resolves to the sameness' '

View File

@ -68,7 +68,8 @@ test_expect_success 'will not overwrite removed file' '
git commit -m "rm c1.c" &&
cp important c1.c &&
test_must_fail git merge c1a &&
test_cmp important c1.c
test_cmp important c1.c &&
rm c1.c # Do not leave untracked file in way of future tests
'
test_expect_success 'will not overwrite re-added file' '

View File

@ -585,6 +585,7 @@ test_expect_success 'checkout --conflict=diff3' '
'
test_expect_success 'failing checkout -b should not break working tree' '
git clean -fd && # Remove untracked files in the way
git reset --hard main &&
git symbolic-ref HEAD refs/heads/main &&
test_must_fail git checkout -b renamer side^ &&

View File

@ -717,6 +717,7 @@ test_expect_success 'failed fast-forward merge with --autostash' '
git reset --hard c0 &&
git merge-file file file.orig file.5 &&
cp file.5 other &&
test_when_finished "rm other" &&
test_must_fail git merge --autostash c1 2>err &&
test_i18ngrep "Applied autostash." err &&
test_cmp file.5 file

View File

@ -277,7 +277,7 @@ test_expect_success 'incremental-repack task' '
# Delete refs that have not been repacked in these packs.
git for-each-ref --format="delete %(refname)" \
refs/prefetch refs/tags >refs &&
refs/prefetch refs/tags refs/remotes >refs &&
git update-ref --stdin <refs &&
# Replace the object directory with this pack layout.
@ -286,6 +286,10 @@ test_expect_success 'incremental-repack task' '
ls $packDir/*.pack >packs-before &&
test_line_count = 3 packs-before &&
# make sure we do not have any broken refs that were
# missed in the deletion above
git for-each-ref &&
# the job repacks the two into a new pack, but does not
# delete the old ones.
git maintenance run --task=incremental-repack &&

View File

@ -534,7 +534,7 @@ SQ=\'
# when case-folding filenames
u200c=$(printf '\342\200\214')
export _x05 _x35 _x40 _z40 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX
export _x05 _x35 LF u200c EMPTY_TREE EMPTY_BLOB ZERO_OID OID_REGEX
# Each test should start with something like this, after copyright notices:
#
@ -1425,10 +1425,9 @@ then
fi
# Convenience
# A regexp to match 5, 35 and 40 hexdigits
# A regexp to match 5 and 35 hexdigits
_x05='[0-9a-f][0-9a-f][0-9a-f][0-9a-f][0-9a-f]'
_x35="$_x05$_x05$_x05$_x05$_x05$_x05$_x05"
_x40="$_x35$_x05"
test_oid_init
@ -1437,7 +1436,6 @@ OID_REGEX=$(echo $ZERO_OID | sed -e 's/0/[0-9a-f]/g')
OIDPATH_REGEX=$(test_oid_to_path $ZERO_OID | sed -e 's/0/[0-9a-f]/g')
EMPTY_TREE=$(test_oid empty_tree)
EMPTY_BLOB=$(test_oid empty_blob)
_z40=$ZERO_OID
# Provide an implementation of the 'yes' utility; the upper bound
# limit is there to help Windows that cannot stop this loop from

View File

@ -21,7 +21,9 @@
ALLOC_ARRAY((x), nr); \
} while(0)
#define FAST_ARRAY_FREE(x, nr) do { \
if ((nr) > 2) \
if ((nr) <= 2) \
xalloca_free((x)); \
else \
free((x)); \
} while(0)