зеркало из https://github.com/microsoft/git.git
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:
Коммит
b6b210c5e1
|
@ -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).
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
-------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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`.
|
||||
|
|
|
@ -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
15
INSTALL
|
@ -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
|
||||
|
|
11
Makefile
11
Makefile
|
@ -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"
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 @@ finish:
|
|||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
9
cache.h
9
cache.h
|
@ -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).
|
||||
*/
|
||||
|
|
3
config.c
3
config.c
|
@ -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)
|
||||
|
|
|
@ -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
2
dir.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;;
|
||||
*)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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
|
||||
;;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
35
http.c
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
37
midx.c
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
5
oidset.c
5
oidset.c
|
@ -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);
|
||||
|
|
5
oidset.h
5
oidset.h
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
38
packfile.c
38
packfile.c
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) &&
|
||||
|
|
|
@ -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), \
|
||||
|
|
22
ref-filter.c
22
ref-filter.c
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
42
refs.c
|
@ -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
9
refs.h
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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).
|
||||
|
|
4
strvec.h
4
strvec.h
|
@ -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 }
|
||||
|
|
77
submodule.c
77
submodule.c
|
@ -1845,14 +1845,16 @@ out:
|
|||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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/
|
||||
|
|
|
@ -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' '
|
||||
|
|
|
@ -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
|
||||
'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
'
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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
|
||||
'
|
||||
|
||||
|
|
|
@ -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
|
||||
'
|
||||
|
||||
|
|
|
@ -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^
|
||||
'
|
||||
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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" &&
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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' '
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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' '
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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' '
|
||||
|
|
|
@ -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' '
|
||||
|
|
|
@ -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^ &&
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 &&
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче