Merge branch 'ps/refname-avail-check-optim' into kn/non-transactional-batch-updates
* ps/refname-avail-check-optim: (43 commits) refs: reuse iterators when determining refname availability refs/iterator: implement seeking for files iterators refs/iterator: implement seeking for packed-ref iterators refs/iterator: implement seeking for ref-cache iterators refs/iterator: implement seeking for reftable iterators refs/iterator: implement seeking for merged iterators refs/iterator: provide infrastructure to re-seek iterators refs/iterator: separate lifecycle from iteration refs: stop re-verifying common prefixes for availability refs/files: batch refname availability checks for initial transactions refs/files: batch refname availability checks for normal transactions refs/reftable: batch refname availability checks refs: introduce function to batch refname availability checks builtin/update-ref: skip ambiguity checks when parsing object IDs object-name: allow skipping ambiguity checks in `get_oid()` family object-name: introduce `repo_get_oid_with_flags()` Git 2.49-rc0 The fourteenth batch mailmap: fix check-mailmap with full mailmap line The thirteenth batch ...maint
commit
7c42ab2c92
|
|
@ -1,3 +1,6 @@
|
|||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
# Import tree-wide shared Makefile behavior and libraries
|
||||
include ../shared.mak
|
||||
|
||||
|
|
@ -238,7 +241,7 @@ DEFAULT_EDITOR_SQ = $(subst ','\'',$(DEFAULT_EDITOR))
|
|||
ASCIIDOC_EXTRA += -a 'git-default-editor=$(DEFAULT_EDITOR_SQ)'
|
||||
endif
|
||||
|
||||
all: html man
|
||||
all:: html man
|
||||
|
||||
html: $(DOC_HTML)
|
||||
|
||||
|
|
|
|||
|
|
@ -33,6 +33,11 @@ UI, Workflows & Features
|
|||
* "git rev-list --missing=" learned to accept "print-info" that gives
|
||||
known details expected of the missing objects, like path and type.
|
||||
|
||||
* Comes with an updated "gitk".
|
||||
|
||||
* The documentation of "git commit" and "git rebase" now refer to
|
||||
commit titles as such, not "subject".
|
||||
|
||||
|
||||
Performance, Internal Implementation, Development Support etc.
|
||||
--------------------------------------------------------------
|
||||
|
|
@ -202,6 +207,25 @@ Fixes since v2.48
|
|||
* A thunderbird helper script lost its bashism.
|
||||
(merge 59d26bd961 bc/contrib-thunderbird-patch-inline-fix later to maint).
|
||||
|
||||
* The -G/-S options to the "diff" family of commands caused us to hit
|
||||
a BUG() when they get no values; they have been corrected.
|
||||
(merge a620046b29 bc/diff-reject-empty-arg-to-pickaxe later to maint).
|
||||
|
||||
* "git merge-tree --stdin" has been improved (including a workaround
|
||||
for a deadlock).
|
||||
(merge 6a9ae81015 pw/merge-tree-stdin-deadlock-fix later to maint).
|
||||
|
||||
* Correct the default target in Documentation/Makefile, and
|
||||
future-proof all Makefiles from similar breakages by declaring the
|
||||
default target (which happens to be "all") upfront.
|
||||
(merge 5309c1e9fb ad/set-default-target-in-makefiles later to maint).
|
||||
|
||||
* "git check-mailmap" used to segfault when queried without human
|
||||
readable name.
|
||||
(merge bb60c52131 jk/check-mailmap-wo-name-fix later to maint).
|
||||
|
||||
* Support for renaming of symbolic links on Windows has been improved.
|
||||
|
||||
* Other code cleanup, docfix, build fix, etc.
|
||||
(merge ddb5287894 jk/t7407-use-test-grep later to maint).
|
||||
(merge 21e1b44865 aj/difftool-config-doc-fix later to maint).
|
||||
|
|
@ -217,3 +241,6 @@ Fixes since v2.48
|
|||
(merge 087740d65a ps/leakfixes-0129 later to maint).
|
||||
(merge 6bba6f604b jp/doc-trailer-config later to maint).
|
||||
(merge f1cc562b77 lo/t7603-path-is-file-update later to maint).
|
||||
(merge 45761988ac en/doc-renormalize later to maint).
|
||||
(merge 832f56f06a jc/doc-boolean-synonyms later to maint).
|
||||
(merge 3eeed876a9 ac/doc-http-ssl-type-config later to maint).
|
||||
|
|
|
|||
|
|
@ -216,6 +216,21 @@ http.sslBackend::
|
|||
This option is ignored if cURL lacks support for choosing the SSL
|
||||
backend at runtime.
|
||||
|
||||
http.sslCertType::
|
||||
Type of client certificate used when fetching or pushing over HTTPS.
|
||||
"PEM", "DER" are supported when using openssl or gnutls backends. "P12"
|
||||
is supported on "openssl", "schannel", "securetransport", and gnutls 8.11+.
|
||||
See also libcurl `CURLOPT_SSLCERTTYPE`. Can be overridden by the
|
||||
`GIT_SSL_CERT_TYPE` environment variable.
|
||||
|
||||
http.sslKeyType::
|
||||
Type of client private key used when fetching or pushing over HTTPS. (e.g.
|
||||
"PEM", "DER", or "ENG"). Only applicable when using "openssl" backend. "DER"
|
||||
is not supported with openssl. Particularly useful when set to "ENG" for
|
||||
authenticating with PKCS#11 tokens, with a PKCS#11 URL in sslCert option.
|
||||
See also libcurl `CURLOPT_SSLKEYTYPE`. Can be overridden by the
|
||||
`GIT_SSL_KEY_TYPE` environment variable.
|
||||
|
||||
http.schannelCheckRevoke::
|
||||
Used to enforce or disable certificate revocation checks in cURL
|
||||
when http.sslBackend is set to "schannel". Defaults to `true` if
|
||||
|
|
|
|||
|
|
@ -69,7 +69,8 @@ merge.renormalize::
|
|||
Tell Git that canonical representation of files in the
|
||||
repository has changed over time (e.g. earlier commits record
|
||||
text files with CRLF line endings, but recent ones use LF line
|
||||
endings). In such a repository, Git can convert the data
|
||||
endings). In such a repository, for each file where a
|
||||
three-way content merge is needed, Git can convert the data
|
||||
recorded in commits to a canonical form before performing a
|
||||
merge to reduce unnecessary conflicts. For more information,
|
||||
see section "Merging branches with differing checkin/checkout
|
||||
|
|
|
|||
|
|
@ -98,8 +98,8 @@ OPTIONS
|
|||
replaces the log message of _<commit>_ with its own log message
|
||||
but makes no changes to the content of _<commit>_.
|
||||
+
|
||||
The commit created by plain `--fixup=<commit>` has a subject
|
||||
composed of "fixup!" followed by the subject line from _<commit>_,
|
||||
The commit created by plain `--fixup=<commit>` has a title
|
||||
composed of "fixup!" followed by the title of _<commit>_,
|
||||
and is recognized specially by `git rebase --autosquash`. The `-m`
|
||||
option may be used to supplement the log message of the created
|
||||
commit, but the additional commentary will be thrown away once the
|
||||
|
|
@ -107,7 +107,7 @@ commit, but the additional commentary will be thrown away once the
|
|||
`git rebase --autosquash`.
|
||||
+
|
||||
The commit created by `--fixup=amend:<commit>` is similar but its
|
||||
subject is instead prefixed with "amend!". The log message of
|
||||
title is instead prefixed with "amend!". The log message of
|
||||
_<commit>_ is copied into the log message of the "amend!" commit and
|
||||
opened in an editor so it can be refined. When `git rebase
|
||||
--autosquash` squashes the "amend!" commit into _<commit>_, the
|
||||
|
|
@ -128,7 +128,7 @@ See linkgit:git-rebase[1] for details.
|
|||
|
||||
`--squash=<commit>`::
|
||||
Construct a commit message for use with `git rebase --autosquash`.
|
||||
The commit message subject line is taken from the specified
|
||||
The commit message title is taken from the specified
|
||||
commit with a prefix of "squash! ". Can be used with additional
|
||||
commit message options (`-m`/`-c`/`-C`/`-F`). See
|
||||
linkgit:git-rebase[1] for details.
|
||||
|
|
|
|||
|
|
@ -213,7 +213,9 @@ See also <<FILES>>.
|
|||
+
|
||||
Valid `<type>`'s include:
|
||||
+
|
||||
- 'bool': canonicalize values as either "true" or "false".
|
||||
- 'bool': canonicalize values `true`, `yes`,`on`, and positive
|
||||
numbers as "true", and values `false`, `no`, `off` and `0` as
|
||||
"false".
|
||||
- 'int': canonicalize values as simple decimal numbers. An optional suffix of
|
||||
'k', 'm', or 'g' will cause the value to be multiplied by 1024, 1048576, or
|
||||
1073741824 upon input.
|
||||
|
|
|
|||
|
|
@ -40,11 +40,17 @@ After the merge completes, a new toplevel tree object is created. See
|
|||
OPTIONS
|
||||
-------
|
||||
|
||||
--stdin::
|
||||
Read the commits to merge from the standard input rather than
|
||||
the command-line. See <<INPUT,INPUT FORMAT>> below for more
|
||||
information. Implies `-z`.
|
||||
|
||||
-z::
|
||||
Do not quote filenames in the <Conflicted file info> section,
|
||||
and end each filename with a NUL character rather than
|
||||
newline. Also begin the messages section with a NUL character
|
||||
instead of a newline. See <<OUTPUT>> below for more information.
|
||||
instead of a newline. See <<OUTPUT,OUTPUT>> below for more
|
||||
information.
|
||||
|
||||
--name-only::
|
||||
In the Conflicted file info section, instead of writing a list
|
||||
|
|
@ -116,8 +122,6 @@ This is an integer status followed by a NUL character. The integer status is:
|
|||
|
||||
0: merge had conflicts
|
||||
1: merge was clean
|
||||
<0: something prevented the merge from running (e.g. access to repository
|
||||
objects denied by filesystem)
|
||||
|
||||
[[OIDTLT]]
|
||||
OID of toplevel tree
|
||||
|
|
@ -235,6 +239,7 @@ with linkgit:git-merge[1]:
|
|||
* any messages that would have been printed to stdout (the
|
||||
<<IM,Informational messages>>)
|
||||
|
||||
[[INPUT]]
|
||||
INPUT FORMAT
|
||||
------------
|
||||
'git merge-tree --stdin' input format is fully text based. Each line
|
||||
|
|
|
|||
|
|
@ -599,11 +599,11 @@ See also INCOMPATIBLE OPTIONS below.
|
|||
--no-autosquash::
|
||||
Automatically squash commits with specially formatted messages into
|
||||
previous commits being rebased. If a commit message starts with
|
||||
"squash! ", "fixup! " or "amend! ", the remainder of the subject line
|
||||
"squash! ", "fixup! " or "amend! ", the remainder of the title
|
||||
is taken as a commit specifier, which matches a previous commit if it
|
||||
matches the subject line or the hash of that commit. If no commit
|
||||
matches the title or the hash of that commit. If no commit
|
||||
matches fully, matches of the specifier with the start of commit
|
||||
subjects are considered.
|
||||
titles are considered.
|
||||
+
|
||||
In the rebase todo list, the actions of squash, fixup and amend commits are
|
||||
changed from `pick` to `squash`, `fixup` or `fixup -C`, respectively, and they
|
||||
|
|
@ -613,7 +613,7 @@ be used to review and edit the todo list before proceeding.
|
|||
The recommended way to create commits with squash markers is by using the
|
||||
`--squash`, `--fixup`, `--fixup=amend:` or `--fixup=reword:` options of
|
||||
linkgit:git-commit[1], which take the target commit as an argument and
|
||||
automatically fill in the subject line of the new commit from that.
|
||||
automatically fill in the title of the new commit from that.
|
||||
+
|
||||
Setting configuration variable `rebase.autoSquash` to true enables
|
||||
auto-squashing by default for interactive rebase. The `--no-autosquash`
|
||||
|
|
|
|||
|
|
@ -472,8 +472,9 @@ Environment Variables
|
|||
---------------------
|
||||
Various Git commands pay attention to environment variables and change
|
||||
their behavior. The environment variables marked as "Boolean" take
|
||||
their values the same way as Boolean valued configuration variables, e.g.
|
||||
"true", "yes", "on" and positive numbers are taken as "yes".
|
||||
their values the same way as Boolean valued configuration variables, i.e.,
|
||||
"true", "yes", "on" and positive numbers are taken as "yes", while "false",
|
||||
"no", "off", and "0" are taken as "no".
|
||||
|
||||
Here are the variables:
|
||||
|
||||
|
|
|
|||
|
|
@ -701,8 +701,8 @@ where the attribute is not in place would normally cause merge
|
|||
conflicts.
|
||||
|
||||
To prevent these unnecessary merge conflicts, Git can be told to run a
|
||||
virtual check-out and check-in of all three stages of a file when
|
||||
resolving a three-way merge by setting the `merge.renormalize`
|
||||
virtual check-out and check-in of all three stages of each file that
|
||||
needs a three-way content merge, by setting the `merge.renormalize`
|
||||
configuration variable. This prevents changes caused by check-in
|
||||
conversion from causing spurious merge conflicts when a converted file
|
||||
is merged with an unconverted file.
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ ignore-cr-at-eol;;
|
|||
|
||||
renormalize;;
|
||||
This runs a virtual check-out and check-in of all three stages
|
||||
of a file when resolving a three-way merge. This option is
|
||||
of any file which needs a three-way merge. This option is
|
||||
meant to be used when merging branches with different clean
|
||||
filters or end-of-line normalization rules. See "Merging
|
||||
branches with differing checkin/checkout attributes" in
|
||||
|
|
|
|||
|
|
@ -339,10 +339,10 @@ insert an empty string unless we are traversing reflog entries (e.g., by
|
|||
decoration format if `--decorate` was not already provided on the command
|
||||
line.
|
||||
|
||||
The boolean options accept an optional value `[=<bool-value>]`. The values
|
||||
`true`, `false`, `on`, `off` etc. are all accepted. See the "boolean"
|
||||
sub-section in "EXAMPLES" in linkgit:git-config[1]. If a boolean
|
||||
option is given with no value, it's enabled.
|
||||
The boolean options accept an optional value `[=<bool-value>]`. The
|
||||
values taken by `--type=bool` git-config[1], like `yes` and `off`,
|
||||
are all accepted. Giving a boolean option without `=<value>` is
|
||||
equivalent to giving it with `=true`.
|
||||
|
||||
If you add a `+` (plus sign) after '%' of a placeholder, a line-feed
|
||||
is inserted immediately before the expansion if and only if the
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#!/bin/sh
|
||||
|
||||
DEF_VER=v2.48.GIT
|
||||
DEF_VER=v2.49.0-rc0
|
||||
|
||||
LF='
|
||||
'
|
||||
|
|
|
|||
8
Makefile
8
Makefile
|
|
@ -1704,16 +1704,16 @@ IMAP_SEND_LDFLAGS += $(OPENSSL_LINK) $(OPENSSL_LIBSSL) $(LIB_4_CRYPTO)
|
|||
|
||||
ifdef ZLIB_NG
|
||||
BASIC_CFLAGS += -DHAVE_ZLIB_NG
|
||||
ifdef ZLIB_NG_PATH
|
||||
ifdef ZLIB_NG_PATH
|
||||
BASIC_CFLAGS += -I$(ZLIB_NG_PATH)/include
|
||||
EXTLIBS += $(call libpath_template,$(ZLIB_NG_PATH)/$(lib))
|
||||
endif
|
||||
endif
|
||||
EXTLIBS += -lz-ng
|
||||
else
|
||||
ifdef ZLIB_PATH
|
||||
ifdef ZLIB_PATH
|
||||
BASIC_CFLAGS += -I$(ZLIB_PATH)/include
|
||||
EXTLIBS += $(call libpath_template,$(ZLIB_PATH)/$(lib))
|
||||
endif
|
||||
endif
|
||||
EXTLIBS += -lz
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ static void check_mailmap(struct string_list *mailmap, const char *contact)
|
|||
mail = ident.mail_begin;
|
||||
maillen = ident.mail_end - ident.mail_begin;
|
||||
} else {
|
||||
name = NULL;
|
||||
name = "";
|
||||
namelen = 0;
|
||||
mail = contact;
|
||||
maillen = strlen(contact);
|
||||
|
|
|
|||
|
|
@ -342,6 +342,8 @@ static void copy_or_link_directory(struct strbuf *src, struct strbuf *dest,
|
|||
strbuf_setlen(src, src_len);
|
||||
die(_("failed to iterate over '%s'"), src->buf);
|
||||
}
|
||||
|
||||
dir_iterator_free(iter);
|
||||
}
|
||||
|
||||
static void clone_local(const char *src_repo, const char *dest_repo)
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "tree.h"
|
||||
#include "config.h"
|
||||
#include "strvec.h"
|
||||
#include "write-or-die.h"
|
||||
|
||||
static int line_termination = '\n';
|
||||
|
||||
|
|
@ -575,7 +576,7 @@ int cmd_merge_tree(int argc,
|
|||
};
|
||||
|
||||
/* Init merge options */
|
||||
init_ui_merge_options(&o.merge_options, the_repository);
|
||||
init_basic_merge_options(&o.merge_options, the_repository);
|
||||
|
||||
/* Parse arguments */
|
||||
original_argc = argc - 1; /* ignoring argv[0] */
|
||||
|
|
@ -600,7 +601,6 @@ int cmd_merge_tree(int argc,
|
|||
line_termination = '\0';
|
||||
while (strbuf_getline_lf(&buf, stdin) != EOF) {
|
||||
struct strbuf **split;
|
||||
int result;
|
||||
const char *input_merge_base = NULL;
|
||||
|
||||
split = strbuf_split(&buf, ' ');
|
||||
|
|
@ -617,15 +617,14 @@ int cmd_merge_tree(int argc,
|
|||
if (input_merge_base && split[2] && split[3] && !split[4]) {
|
||||
strbuf_rtrim(split[2]);
|
||||
strbuf_rtrim(split[3]);
|
||||
result = real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
|
||||
real_merge(&o, input_merge_base, split[2]->buf, split[3]->buf, prefix);
|
||||
} else if (!input_merge_base && !split[2]) {
|
||||
result = real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
|
||||
real_merge(&o, NULL, split[0]->buf, split[1]->buf, prefix);
|
||||
} else {
|
||||
die(_("malformed input line: '%s'."), buf.buf);
|
||||
}
|
||||
maybe_flush_or_die(stdout, "stdout");
|
||||
|
||||
if (result < 0)
|
||||
die(_("merging cannot continue; got unclean result of %d"), result);
|
||||
strbuf_list_free(split);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
|
|
|
|||
|
|
@ -179,7 +179,8 @@ static int parse_next_oid(const char **next, const char *end,
|
|||
(*next)++;
|
||||
*next = parse_arg(*next, &arg);
|
||||
if (arg.len) {
|
||||
if (repo_get_oid(the_repository, arg.buf, oid))
|
||||
if (repo_get_oid_with_flags(the_repository, arg.buf, oid,
|
||||
GET_OID_SKIP_AMBIGUITY_CHECK))
|
||||
goto invalid;
|
||||
} else {
|
||||
/* Without -z, an empty value means all zeros: */
|
||||
|
|
@ -197,7 +198,8 @@ static int parse_next_oid(const char **next, const char *end,
|
|||
*next += arg.len;
|
||||
|
||||
if (arg.len) {
|
||||
if (repo_get_oid(the_repository, arg.buf, oid))
|
||||
if (repo_get_oid_with_flags(the_repository, arg.buf, oid,
|
||||
GET_OID_SKIP_AMBIGUITY_CHECK))
|
||||
goto invalid;
|
||||
} else if (flags & PARSE_SHA1_ALLOW_EMPTY) {
|
||||
/* With -z, treat an empty value as all zeros: */
|
||||
|
|
@ -299,7 +301,8 @@ static void parse_cmd_symref_update(struct ref_transaction *transaction,
|
|||
die("symref-update %s: expected old value", refname);
|
||||
|
||||
if (!strcmp(old_arg, "oid")) {
|
||||
if (repo_get_oid(the_repository, old_target, &old_oid))
|
||||
if (repo_get_oid_with_flags(the_repository, old_target, &old_oid,
|
||||
GET_OID_SKIP_AMBIGUITY_CHECK))
|
||||
die("symref-update %s: invalid oid: %s", refname, old_target);
|
||||
|
||||
have_old_oid = 1;
|
||||
|
|
@ -772,7 +775,8 @@ int cmd_update_ref(int argc,
|
|||
refname = argv[0];
|
||||
value = argv[1];
|
||||
oldval = argv[2];
|
||||
if (repo_get_oid(the_repository, value, &oid))
|
||||
if (repo_get_oid_with_flags(the_repository, value, &oid,
|
||||
GET_OID_SKIP_AMBIGUITY_CHECK))
|
||||
die("%s: not a valid SHA1", value);
|
||||
}
|
||||
|
||||
|
|
@ -783,7 +787,8 @@ int cmd_update_ref(int argc,
|
|||
* must not already exist:
|
||||
*/
|
||||
oidclr(&oldoid, the_repository->hash_algo);
|
||||
else if (repo_get_oid(the_repository, oldval, &oldoid))
|
||||
else if (repo_get_oid_with_flags(the_repository, oldval, &oldoid,
|
||||
GET_OID_SKIP_AMBIGUITY_CHECK))
|
||||
die("%s: not a valid old SHA1", oldval);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#define USE_THE_REPOSITORY_VARIABLE
|
||||
#include "builtin.h"
|
||||
#include "config.h"
|
||||
#include "gettext.h"
|
||||
|
|
@ -13,7 +12,7 @@ static const char * const update_server_info_usage[] = {
|
|||
int cmd_update_server_info(int argc,
|
||||
const char **argv,
|
||||
const char *prefix,
|
||||
struct repository *repo UNUSED)
|
||||
struct repository *repo)
|
||||
{
|
||||
int force = 0;
|
||||
struct option options[] = {
|
||||
|
|
@ -21,11 +20,12 @@ int cmd_update_server_info(int argc,
|
|||
OPT_END()
|
||||
};
|
||||
|
||||
git_config(git_default_config, NULL);
|
||||
if (repo)
|
||||
repo_config(repo, git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, options,
|
||||
update_server_info_usage, 0);
|
||||
if (argc > 0)
|
||||
usage_with_options(update_server_info_usage, options);
|
||||
|
||||
return !!update_server_info(the_repository, force);
|
||||
return !!update_server_info(repo, force);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2278,7 +2278,9 @@ repeat:
|
|||
|
||||
old_handle = CreateFileW(wpold, DELETE,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
|
||||
NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
|
||||
NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
|
||||
NULL);
|
||||
if (old_handle == INVALID_HANDLE_VALUE) {
|
||||
errno = err_win_to_posix(GetLastError());
|
||||
return -1;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
MAIN:=git-credential-libsecret
|
||||
all:: $(MAIN)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# The default target of this Makefile is...
|
||||
all:: git-credential-osxkeychain
|
||||
|
||||
CC = gcc
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
all: git-credential-wincred.exe
|
||||
# The default target of this Makefile is...
|
||||
all:: git-credential-wincred.exe
|
||||
|
||||
-include ../../../config.mak.autogen
|
||||
-include ../../../config.mak
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
all: diff-highlight
|
||||
# The default target of this Makefile is...
|
||||
all:: diff-highlight
|
||||
|
||||
PERL_PATH = /usr/bin/perl
|
||||
-include ../../config.mak
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
-include ../../../config.mak.autogen
|
||||
-include ../../../config.mak
|
||||
|
||||
|
|
@ -6,7 +9,7 @@ SHELL_PATH ?= $(SHELL)
|
|||
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
|
||||
T = $(wildcard t[0-9][0-9][0-9][0-9]-*.sh)
|
||||
|
||||
all: test
|
||||
all:: test
|
||||
test: $(T)
|
||||
|
||||
.PHONY: help clean all test $(T)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,9 @@
|
|||
#
|
||||
# make install
|
||||
|
||||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
GIT_MEDIAWIKI_PM=Git/Mediawiki.pm
|
||||
SCRIPT_PERL=git-remote-mediawiki.perl
|
||||
SCRIPT_PERL+=git-mw.perl
|
||||
|
|
@ -27,7 +30,7 @@ INSTLIBDIR=$(shell $(MAKE) -C $(GIT_ROOT_DIR)/ \
|
|||
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
|
||||
INSTLIBDIR_SQ = $(subst ','\'',$(INSTLIBDIR))
|
||||
|
||||
all: build
|
||||
all:: build
|
||||
|
||||
test: all
|
||||
$(MAKE) -C t
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@
|
|||
#
|
||||
## Test git-remote-mediawiki
|
||||
|
||||
all: test
|
||||
# The default target of this Makefile is...
|
||||
all:: test
|
||||
|
||||
-include ../../../config.mak.autogen
|
||||
-include ../../../config.mak
|
||||
|
|
|
|||
|
|
@ -12,10 +12,13 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
BUILD_LABEL=$(shell cut -d" " -f3 ../../GIT-VERSION-FILE)
|
||||
TAR_OUT=$(shell go env GOOS)_$(shell go env GOARCH).tar.gz
|
||||
|
||||
all: git-remote-persistent-https git-remote-persistent-https--proxy \
|
||||
all:: git-remote-persistent-https git-remote-persistent-https--proxy \
|
||||
git-remote-persistent-http
|
||||
|
||||
git-remote-persistent-https--proxy: git-remote-persistent-https
|
||||
|
|
|
|||
|
|
@ -3,6 +3,9 @@
|
|||
# Copyright (c) 2005 Junio C Hamano
|
||||
#
|
||||
|
||||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
-include ../../../config.mak.autogen
|
||||
-include ../../../config.mak
|
||||
|
||||
|
|
@ -31,7 +34,7 @@ TSVN = $(sort $(wildcard t91[0-9][0-9]-*.sh))
|
|||
TGITWEB = $(sort $(wildcard t95[0-9][0-9]-*.sh))
|
||||
THELPERS = $(sort $(filter-out $(T),$(wildcard *.sh)))
|
||||
|
||||
all: $(DEFAULT_TEST_TARGET)
|
||||
all:: $(DEFAULT_TEST_TARGET)
|
||||
|
||||
test: pre-clean $(TEST_LINT)
|
||||
$(MAKE) aggregate-results-and-cleanup
|
||||
|
|
|
|||
4
diff.c
4
diff.c
|
|
@ -5493,6 +5493,8 @@ static int diff_opt_pickaxe_regex(const struct option *opt,
|
|||
BUG_ON_OPT_NEG(unset);
|
||||
options->pickaxe = arg;
|
||||
options->pickaxe_opts |= DIFF_PICKAXE_KIND_G;
|
||||
if (arg && !*arg)
|
||||
return error(_("-G requires a non-empty argument"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -5504,6 +5506,8 @@ static int diff_opt_pickaxe_string(const struct option *opt,
|
|||
BUG_ON_OPT_NEG(unset);
|
||||
options->pickaxe = arg;
|
||||
options->pickaxe_opts |= DIFF_PICKAXE_KIND_S;
|
||||
if (arg && !*arg)
|
||||
return error(_("-S requires a non-empty argument"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -193,9 +193,9 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator)
|
|||
|
||||
if (S_ISDIR(iter->base.st.st_mode) && push_level(iter)) {
|
||||
if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC)
|
||||
goto error_out;
|
||||
return ITER_ERROR;
|
||||
if (iter->levels_nr == 0)
|
||||
goto error_out;
|
||||
return ITER_ERROR;
|
||||
}
|
||||
|
||||
/* Loop until we find an entry that we can give back to the caller. */
|
||||
|
|
@ -211,11 +211,11 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator)
|
|||
int ret = next_directory_entry(level->dir, iter->base.path.buf, &de);
|
||||
if (ret < 0) {
|
||||
if (iter->flags & DIR_ITERATOR_PEDANTIC)
|
||||
goto error_out;
|
||||
return ITER_ERROR;
|
||||
continue;
|
||||
} else if (ret > 0) {
|
||||
if (pop_level(iter) == 0)
|
||||
return dir_iterator_abort(dir_iterator);
|
||||
return ITER_DONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator)
|
|||
} else {
|
||||
if (level->entries_idx >= level->entries.nr) {
|
||||
if (pop_level(iter) == 0)
|
||||
return dir_iterator_abort(dir_iterator);
|
||||
return ITER_DONE;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -232,22 +232,21 @@ int dir_iterator_advance(struct dir_iterator *dir_iterator)
|
|||
|
||||
if (prepare_next_entry_data(iter, name)) {
|
||||
if (errno != ENOENT && iter->flags & DIR_ITERATOR_PEDANTIC)
|
||||
goto error_out;
|
||||
return ITER_ERROR;
|
||||
continue;
|
||||
}
|
||||
|
||||
return ITER_OK;
|
||||
}
|
||||
|
||||
error_out:
|
||||
dir_iterator_abort(dir_iterator);
|
||||
return ITER_ERROR;
|
||||
}
|
||||
|
||||
int dir_iterator_abort(struct dir_iterator *dir_iterator)
|
||||
void dir_iterator_free(struct dir_iterator *dir_iterator)
|
||||
{
|
||||
struct dir_iterator_int *iter = (struct dir_iterator_int *)dir_iterator;
|
||||
|
||||
if (!iter)
|
||||
return;
|
||||
|
||||
for (; iter->levels_nr; iter->levels_nr--) {
|
||||
struct dir_iterator_level *level =
|
||||
&iter->levels[iter->levels_nr - 1];
|
||||
|
|
@ -266,7 +265,6 @@ int dir_iterator_abort(struct dir_iterator *dir_iterator)
|
|||
free(iter->levels);
|
||||
strbuf_release(&iter->base.path);
|
||||
free(iter);
|
||||
return ITER_DONE;
|
||||
}
|
||||
|
||||
struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags)
|
||||
|
|
@ -301,7 +299,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags)
|
|||
return dir_iterator;
|
||||
|
||||
error_out:
|
||||
dir_iterator_abort(dir_iterator);
|
||||
dir_iterator_free(dir_iterator);
|
||||
errno = saved_errno;
|
||||
return NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@
|
|||
*
|
||||
* while ((ok = dir_iterator_advance(iter)) == ITER_OK) {
|
||||
* if (want_to_stop_iteration()) {
|
||||
* ok = dir_iterator_abort(iter);
|
||||
* ok = ITER_DONE;
|
||||
* break;
|
||||
* }
|
||||
*
|
||||
|
|
@ -39,6 +39,7 @@
|
|||
*
|
||||
* if (ok != ITER_DONE)
|
||||
* handle_error();
|
||||
* dir_iterator_free(iter);
|
||||
*
|
||||
* Callers are allowed to modify iter->path while they are working,
|
||||
* but they must restore it to its original contents before calling
|
||||
|
|
@ -107,11 +108,7 @@ struct dir_iterator *dir_iterator_begin(const char *path, unsigned int flags);
|
|||
*/
|
||||
int dir_iterator_advance(struct dir_iterator *iterator);
|
||||
|
||||
/*
|
||||
* End the iteration before it has been exhausted. Free the
|
||||
* dir_iterator and any associated resources and return ITER_DONE. On
|
||||
* error, free the dir_iterator and return ITER_ERROR.
|
||||
*/
|
||||
int dir_iterator_abort(struct dir_iterator *iterator);
|
||||
/* Free the dir_iterator and any associated resources. */
|
||||
void dir_iterator_free(struct dir_iterator *iterator);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
# Define V=1 to have a more verbose compile.
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# The default target of this Makefile is...
|
||||
update-po::
|
||||
|
||||
PO_TEMPLATE = git-gui-glossary.pot
|
||||
|
||||
ALL_POFILES = $(wildcard *.po)
|
||||
|
|
|
|||
23
hash.h
23
hash.h
|
|
@ -193,17 +193,18 @@ struct object_id {
|
|||
int algo; /* XXX requires 4-byte alignment */
|
||||
};
|
||||
|
||||
#define GET_OID_QUIETLY 01
|
||||
#define GET_OID_COMMIT 02
|
||||
#define GET_OID_COMMITTISH 04
|
||||
#define GET_OID_TREE 010
|
||||
#define GET_OID_TREEISH 020
|
||||
#define GET_OID_BLOB 040
|
||||
#define GET_OID_FOLLOW_SYMLINKS 0100
|
||||
#define GET_OID_RECORD_PATH 0200
|
||||
#define GET_OID_ONLY_TO_DIE 04000
|
||||
#define GET_OID_REQUIRE_PATH 010000
|
||||
#define GET_OID_HASH_ANY 020000
|
||||
#define GET_OID_QUIETLY 01
|
||||
#define GET_OID_COMMIT 02
|
||||
#define GET_OID_COMMITTISH 04
|
||||
#define GET_OID_TREE 010
|
||||
#define GET_OID_TREEISH 020
|
||||
#define GET_OID_BLOB 040
|
||||
#define GET_OID_FOLLOW_SYMLINKS 0100
|
||||
#define GET_OID_RECORD_PATH 0200
|
||||
#define GET_OID_ONLY_TO_DIE 04000
|
||||
#define GET_OID_REQUIRE_PATH 010000
|
||||
#define GET_OID_HASH_ANY 020000
|
||||
#define GET_OID_SKIP_AMBIGUITY_CHECK 040000
|
||||
|
||||
#define GET_OID_DISAMBIGUATORS \
|
||||
(GET_OID_COMMIT | GET_OID_COMMITTISH | \
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
#define ITER_OK 0
|
||||
|
||||
/*
|
||||
* The iterator is exhausted and has been freed.
|
||||
* The iterator is exhausted.
|
||||
*/
|
||||
#define ITER_DONE -1
|
||||
|
||||
|
|
|
|||
17
meson.build
17
meson.build
|
|
@ -778,7 +778,22 @@ endif
|
|||
|
||||
# Note that we only set NO_PERL if the Perl features were disabled by the user.
|
||||
# It may not be set when we have found Perl, but only use it to run tests.
|
||||
perl = find_program('perl', version: '>=5.8.1', dirs: program_path, required: perl_required)
|
||||
#
|
||||
# At the time of writing, executing `perl --version` results in a string
|
||||
# similar to the following output:
|
||||
#
|
||||
# This is perl 5, version 40, subversion 0 (v5.40.0) built for x86_64-linux-thread-multi
|
||||
#
|
||||
# Meson picks up the "40" as version number instead of using "v5.40.0"
|
||||
# due to the regular expression it uses. This got fixed in Meson 1.7.0,
|
||||
# but meanwhile we have to either use `-V:version` instead of `--version`,
|
||||
# which we can do starting with Meson 1.5.0 and newer, or we have to
|
||||
# match against the minor version.
|
||||
if meson.version().version_compare('>=1.5.0')
|
||||
perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=5.26.0', version_argument: '-V:version')
|
||||
else
|
||||
perl = find_program('perl', dirs: program_path, required: perl_required, version: '>=26')
|
||||
endif
|
||||
perl_features_enabled = perl.found() and get_option('perl').allowed()
|
||||
if perl_features_enabled
|
||||
build_options_config.set('NO_PERL', '')
|
||||
|
|
|
|||
|
|
@ -961,7 +961,9 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
|
|||
int fatal = !(flags & GET_OID_QUIETLY);
|
||||
|
||||
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
|
||||
if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) {
|
||||
if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) &&
|
||||
repo_settings_get_warn_ambiguous_refs(r) &&
|
||||
warn_on_object_refname_ambiguity) {
|
||||
refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
|
||||
if (refs_found > 0) {
|
||||
warning(warn_msg, len, str);
|
||||
|
|
@ -1794,18 +1796,20 @@ void object_context_release(struct object_context *ctx)
|
|||
strbuf_release(&ctx->symlink_path);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is like "get_oid_basic()", except it allows "object ID expressions",
|
||||
* notably "xyz^" for "parent of xyz"
|
||||
*/
|
||||
int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
|
||||
int repo_get_oid_with_flags(struct repository *r, const char *name,
|
||||
struct object_id *oid, unsigned flags)
|
||||
{
|
||||
struct object_context unused;
|
||||
int ret = get_oid_with_context(r, name, 0, oid, &unused);
|
||||
int ret = get_oid_with_context(r, name, flags, oid, &unused);
|
||||
object_context_release(&unused);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
|
||||
{
|
||||
return repo_get_oid_with_flags(r, name, oid, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* This returns a non-zero value if the string (built using printf
|
||||
* format and the given arguments) is not a valid object.
|
||||
|
|
|
|||
|
|
@ -51,6 +51,12 @@ void strbuf_repo_add_unique_abbrev(struct strbuf *sb, struct repository *repo,
|
|||
void strbuf_add_unique_abbrev(struct strbuf *sb, const struct object_id *oid,
|
||||
int abbrev_len);
|
||||
|
||||
/*
|
||||
* This is like "get_oid_basic()", except it allows "object ID expressions",
|
||||
* notably "xyz^" for "parent of xyz". Accepts GET_OID_* flags.
|
||||
*/
|
||||
int repo_get_oid_with_flags(struct repository *r, const char *str,
|
||||
struct object_id *oid, unsigned flags);
|
||||
int repo_get_oid(struct repository *r, const char *str, struct object_id *oid);
|
||||
__attribute__((format (printf, 2, 3)))
|
||||
int get_oidf(struct object_id *oid, const char *fmt, ...);
|
||||
|
|
|
|||
187
refs.c
187
refs.c
|
|
@ -2475,19 +2475,18 @@ int ref_transaction_commit(struct ref_transaction *transaction,
|
|||
return ret;
|
||||
}
|
||||
|
||||
int refs_verify_refname_available(struct ref_store *refs,
|
||||
const char *refname,
|
||||
const struct string_list *extras,
|
||||
const struct string_list *skip,
|
||||
unsigned int initial_transaction,
|
||||
struct strbuf *err)
|
||||
int refs_verify_refnames_available(struct ref_store *refs,
|
||||
const struct string_list *refnames,
|
||||
const struct string_list *extras,
|
||||
const struct string_list *skip,
|
||||
unsigned int initial_transaction,
|
||||
struct strbuf *err)
|
||||
{
|
||||
const char *slash;
|
||||
const char *extra_refname;
|
||||
struct strbuf dirname = STRBUF_INIT;
|
||||
struct strbuf referent = STRBUF_INIT;
|
||||
struct object_id oid;
|
||||
unsigned int type;
|
||||
struct string_list_item *item;
|
||||
struct ref_iterator *iter = NULL;
|
||||
struct strset dirnames;
|
||||
int ret = -1;
|
||||
|
||||
/*
|
||||
|
|
@ -2497,86 +2496,130 @@ int refs_verify_refname_available(struct ref_store *refs,
|
|||
|
||||
assert(err);
|
||||
|
||||
strbuf_grow(&dirname, strlen(refname) + 1);
|
||||
for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
|
||||
/*
|
||||
* Just saying "Is a directory" when we e.g. can't
|
||||
* lock some multi-level ref isn't very informative,
|
||||
* the user won't be told *what* is a directory, so
|
||||
* let's not use strerror() below.
|
||||
*/
|
||||
int ignore_errno;
|
||||
/* Expand dirname to the new prefix, not including the trailing slash: */
|
||||
strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
|
||||
strset_init(&dirnames);
|
||||
|
||||
/*
|
||||
* We are still at a leading dir of the refname (e.g.,
|
||||
* "refs/foo"; if there is a reference with that name,
|
||||
* it is a conflict, *unless* it is in skip.
|
||||
*/
|
||||
if (skip && string_list_has_string(skip, dirname.buf))
|
||||
continue;
|
||||
for_each_string_list_item(item, refnames) {
|
||||
const char *refname = item->string;
|
||||
const char *extra_refname;
|
||||
struct object_id oid;
|
||||
unsigned int type;
|
||||
const char *slash;
|
||||
|
||||
if (!initial_transaction &&
|
||||
!refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
|
||||
&type, &ignore_errno)) {
|
||||
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
|
||||
dirname.buf, refname);
|
||||
goto cleanup;
|
||||
}
|
||||
strbuf_reset(&dirname);
|
||||
|
||||
if (extras && string_list_has_string(extras, dirname.buf)) {
|
||||
strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
|
||||
refname, dirname.buf);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
for (slash = strchr(refname, '/'); slash; slash = strchr(slash + 1, '/')) {
|
||||
/*
|
||||
* Just saying "Is a directory" when we e.g. can't
|
||||
* lock some multi-level ref isn't very informative,
|
||||
* the user won't be told *what* is a directory, so
|
||||
* let's not use strerror() below.
|
||||
*/
|
||||
int ignore_errno;
|
||||
|
||||
/*
|
||||
* We are at the leaf of our refname (e.g., "refs/foo/bar").
|
||||
* There is no point in searching for a reference with that
|
||||
* name, because a refname isn't considered to conflict with
|
||||
* itself. But we still need to check for references whose
|
||||
* names are in the "refs/foo/bar/" namespace, because they
|
||||
* *do* conflict.
|
||||
*/
|
||||
strbuf_addstr(&dirname, refname + dirname.len);
|
||||
strbuf_addch(&dirname, '/');
|
||||
/* Expand dirname to the new prefix, not including the trailing slash: */
|
||||
strbuf_add(&dirname, refname + dirname.len, slash - refname - dirname.len);
|
||||
|
||||
if (!initial_transaction) {
|
||||
struct ref_iterator *iter;
|
||||
int ok;
|
||||
|
||||
iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN);
|
||||
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
|
||||
if (skip &&
|
||||
string_list_has_string(skip, iter->refname))
|
||||
/*
|
||||
* We are still at a leading dir of the refname (e.g.,
|
||||
* "refs/foo"; if there is a reference with that name,
|
||||
* it is a conflict, *unless* it is in skip.
|
||||
*/
|
||||
if (skip && string_list_has_string(skip, dirname.buf))
|
||||
continue;
|
||||
|
||||
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
|
||||
iter->refname, refname);
|
||||
ref_iterator_abort(iter);
|
||||
goto cleanup;
|
||||
/*
|
||||
* If we've already seen the directory we don't need to
|
||||
* process it again. Skip it to avoid checking checking
|
||||
* common prefixes like "refs/heads/" repeatedly.
|
||||
*/
|
||||
if (!strset_add(&dirnames, dirname.buf))
|
||||
continue;
|
||||
|
||||
if (!initial_transaction &&
|
||||
!refs_read_raw_ref(refs, dirname.buf, &oid, &referent,
|
||||
&type, &ignore_errno)) {
|
||||
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
|
||||
dirname.buf, refname);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (extras && string_list_has_string(extras, dirname.buf)) {
|
||||
strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
|
||||
refname, dirname.buf);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
if (ok != ITER_DONE)
|
||||
BUG("error while iterating over references");
|
||||
/*
|
||||
* We are at the leaf of our refname (e.g., "refs/foo/bar").
|
||||
* There is no point in searching for a reference with that
|
||||
* name, because a refname isn't considered to conflict with
|
||||
* itself. But we still need to check for references whose
|
||||
* names are in the "refs/foo/bar/" namespace, because they
|
||||
* *do* conflict.
|
||||
*/
|
||||
strbuf_addstr(&dirname, refname + dirname.len);
|
||||
strbuf_addch(&dirname, '/');
|
||||
|
||||
if (!initial_transaction) {
|
||||
int ok;
|
||||
|
||||
if (!iter) {
|
||||
iter = refs_ref_iterator_begin(refs, dirname.buf, NULL, 0,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN);
|
||||
} else if (ref_iterator_seek(iter, dirname.buf) < 0) {
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
|
||||
if (skip &&
|
||||
string_list_has_string(skip, iter->refname))
|
||||
continue;
|
||||
|
||||
strbuf_addf(err, _("'%s' exists; cannot create '%s'"),
|
||||
iter->refname, refname);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ok != ITER_DONE)
|
||||
BUG("error while iterating over references");
|
||||
}
|
||||
|
||||
extra_refname = find_descendant_ref(dirname.buf, extras, skip);
|
||||
if (extra_refname) {
|
||||
strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
|
||||
refname, extra_refname);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
extra_refname = find_descendant_ref(dirname.buf, extras, skip);
|
||||
if (extra_refname)
|
||||
strbuf_addf(err, _("cannot process '%s' and '%s' at the same time"),
|
||||
refname, extra_refname);
|
||||
else
|
||||
ret = 0;
|
||||
ret = 0;
|
||||
|
||||
cleanup:
|
||||
strbuf_release(&referent);
|
||||
strbuf_release(&dirname);
|
||||
strset_clear(&dirnames);
|
||||
ref_iterator_free(iter);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int refs_verify_refname_available(struct ref_store *refs,
|
||||
const char *refname,
|
||||
const struct string_list *extras,
|
||||
const struct string_list *skip,
|
||||
unsigned int initial_transaction,
|
||||
struct strbuf *err)
|
||||
{
|
||||
struct string_list_item item = { .string = (char *) refname };
|
||||
struct string_list refnames = {
|
||||
.items = &item,
|
||||
.nr = 1,
|
||||
};
|
||||
|
||||
return refs_verify_refnames_available(refs, &refnames, extras, skip,
|
||||
initial_transaction, err);
|
||||
}
|
||||
|
||||
struct do_for_each_reflog_help {
|
||||
each_reflog_fn *fn;
|
||||
void *cb_data;
|
||||
|
|
|
|||
12
refs.h
12
refs.h
|
|
@ -124,6 +124,18 @@ int refs_verify_refname_available(struct ref_store *refs,
|
|||
unsigned int initial_transaction,
|
||||
struct strbuf *err);
|
||||
|
||||
/*
|
||||
* Same as `refs_verify_refname_available()`, but checking for a list of
|
||||
* refnames instead of only a single item. This is more efficient in the case
|
||||
* where one needs to check multiple refnames.
|
||||
*/
|
||||
int refs_verify_refnames_available(struct ref_store *refs,
|
||||
const struct string_list *refnames,
|
||||
const struct string_list *extras,
|
||||
const struct string_list *skip,
|
||||
unsigned int initial_transaction,
|
||||
struct strbuf *err);
|
||||
|
||||
int refs_ref_exists(struct ref_store *refs, const char *refname);
|
||||
|
||||
int should_autocreate_reflog(enum log_refs_config log_all_ref_updates,
|
||||
|
|
|
|||
20
refs/debug.c
20
refs/debug.c
|
|
@ -169,6 +169,16 @@ static int debug_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
return res;
|
||||
}
|
||||
|
||||
static int debug_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct debug_ref_iterator *diter =
|
||||
(struct debug_ref_iterator *)ref_iterator;
|
||||
int res = diter->iter->vtable->seek(diter->iter, prefix);
|
||||
trace_printf_key(&trace_refs, "iterator_seek: %s: %d\n", prefix ? prefix : "", res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
|
@ -179,19 +189,19 @@ static int debug_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
return res;
|
||||
}
|
||||
|
||||
static int debug_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void debug_ref_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct debug_ref_iterator *diter =
|
||||
(struct debug_ref_iterator *)ref_iterator;
|
||||
int res = diter->iter->vtable->abort(diter->iter);
|
||||
trace_printf_key(&trace_refs, "iterator_abort: %d\n", res);
|
||||
return res;
|
||||
diter->iter->vtable->release(diter->iter);
|
||||
trace_printf_key(&trace_refs, "iterator_abort\n");
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable debug_ref_iterator_vtable = {
|
||||
.advance = debug_ref_iterator_advance,
|
||||
.seek = debug_ref_iterator_seek,
|
||||
.peel = debug_ref_iterator_peel,
|
||||
.abort = debug_ref_iterator_abort,
|
||||
.release = debug_ref_iterator_release,
|
||||
};
|
||||
|
||||
static struct ref_iterator *
|
||||
|
|
|
|||
|
|
@ -678,6 +678,7 @@ static void unlock_ref(struct ref_lock *lock)
|
|||
*/
|
||||
static int lock_raw_ref(struct files_ref_store *refs,
|
||||
const char *refname, int mustexist,
|
||||
struct string_list *refnames_to_check,
|
||||
const struct string_list *extras,
|
||||
struct ref_lock **lock_p,
|
||||
struct strbuf *referent,
|
||||
|
|
@ -855,16 +856,11 @@ retry:
|
|||
}
|
||||
|
||||
/*
|
||||
* If the ref did not exist and we are creating it,
|
||||
* make sure there is no existing packed ref that
|
||||
* conflicts with refname:
|
||||
* If the ref did not exist and we are creating it, we have to
|
||||
* make sure there is no existing packed ref that conflicts
|
||||
* with refname. This check is deferred so that we can batch it.
|
||||
*/
|
||||
if (refs_verify_refname_available(
|
||||
refs->packed_ref_store, refname,
|
||||
extras, NULL, 0, err)) {
|
||||
ret = TRANSACTION_NAME_CONFLICT;
|
||||
goto error_return;
|
||||
}
|
||||
string_list_append(refnames_to_check, refname);
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
|
|
@ -919,13 +915,17 @@ static int files_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
return ITER_OK;
|
||||
}
|
||||
|
||||
iter->iter0 = NULL;
|
||||
if (ref_iterator_abort(ref_iterator) != ITER_DONE)
|
||||
ok = ITER_ERROR;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int files_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct files_ref_iterator *iter =
|
||||
(struct files_ref_iterator *)ref_iterator;
|
||||
return ref_iterator_seek(iter->iter0, prefix);
|
||||
}
|
||||
|
||||
static int files_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
|
@ -935,23 +935,18 @@ static int files_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
return ref_iterator_peel(iter->iter0, peeled);
|
||||
}
|
||||
|
||||
static int files_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void files_ref_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct files_ref_iterator *iter =
|
||||
(struct files_ref_iterator *)ref_iterator;
|
||||
int ok = ITER_DONE;
|
||||
|
||||
if (iter->iter0)
|
||||
ok = ref_iterator_abort(iter->iter0);
|
||||
|
||||
base_ref_iterator_free(ref_iterator);
|
||||
return ok;
|
||||
ref_iterator_free(iter->iter0);
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable files_ref_iterator_vtable = {
|
||||
.advance = files_ref_iterator_advance,
|
||||
.seek = files_ref_iterator_seek,
|
||||
.peel = files_ref_iterator_peel,
|
||||
.abort = files_ref_iterator_abort,
|
||||
.release = files_ref_iterator_release,
|
||||
};
|
||||
|
||||
static struct ref_iterator *files_ref_iterator_begin(
|
||||
|
|
@ -1382,7 +1377,7 @@ static int should_pack_refs(struct files_ref_store *refs,
|
|||
iter->flags, opts))
|
||||
refcount++;
|
||||
if (refcount >= limit) {
|
||||
ref_iterator_abort(iter);
|
||||
ref_iterator_free(iter);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
|
@ -1390,6 +1385,7 @@ static int should_pack_refs(struct files_ref_store *refs,
|
|||
if (ret != ITER_DONE)
|
||||
die("error while iterating over references");
|
||||
|
||||
ref_iterator_free(iter);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -1456,6 +1452,7 @@ static int files_pack_refs(struct ref_store *ref_store,
|
|||
packed_refs_unlock(refs->packed_ref_store);
|
||||
|
||||
prune_refs(refs, &refs_to_prune);
|
||||
ref_iterator_free(iter);
|
||||
strbuf_release(&err);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -2303,35 +2300,33 @@ static int files_reflog_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
return ITER_OK;
|
||||
}
|
||||
|
||||
iter->dir_iterator = NULL;
|
||||
if (ref_iterator_abort(ref_iterator) == ITER_ERROR)
|
||||
ok = ITER_ERROR;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int files_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
|
||||
const char *prefix UNUSED)
|
||||
{
|
||||
BUG("ref_iterator_seek() called for reflog_iterator");
|
||||
}
|
||||
|
||||
static int files_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
|
||||
struct object_id *peeled UNUSED)
|
||||
{
|
||||
BUG("ref_iterator_peel() called for reflog_iterator");
|
||||
}
|
||||
|
||||
static int files_reflog_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void files_reflog_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct files_reflog_iterator *iter =
|
||||
(struct files_reflog_iterator *)ref_iterator;
|
||||
int ok = ITER_DONE;
|
||||
|
||||
if (iter->dir_iterator)
|
||||
ok = dir_iterator_abort(iter->dir_iterator);
|
||||
|
||||
base_ref_iterator_free(ref_iterator);
|
||||
return ok;
|
||||
dir_iterator_free(iter->dir_iterator);
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable files_reflog_iterator_vtable = {
|
||||
.advance = files_reflog_iterator_advance,
|
||||
.seek = files_reflog_iterator_seek,
|
||||
.peel = files_reflog_iterator_peel,
|
||||
.abort = files_reflog_iterator_abort,
|
||||
.release = files_reflog_iterator_release,
|
||||
};
|
||||
|
||||
static struct ref_iterator *reflog_iterator_begin(struct ref_store *ref_store,
|
||||
|
|
@ -2569,6 +2564,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
|
|||
struct ref_update *update,
|
||||
struct ref_transaction *transaction,
|
||||
const char *head_ref,
|
||||
struct string_list *refnames_to_check,
|
||||
struct string_list *affected_refnames,
|
||||
struct strbuf *err)
|
||||
{
|
||||
|
|
@ -2597,7 +2593,7 @@ static int lock_ref_for_update(struct files_ref_store *refs,
|
|||
lock->count++;
|
||||
} else {
|
||||
ret = lock_raw_ref(refs, update->refname, mustexist,
|
||||
affected_refnames,
|
||||
refnames_to_check, affected_refnames,
|
||||
&lock, &referent,
|
||||
&update->type, err);
|
||||
if (ret) {
|
||||
|
|
@ -2811,6 +2807,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
|
|||
size_t i;
|
||||
int ret = 0;
|
||||
struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
|
||||
struct string_list refnames_to_check = STRING_LIST_INIT_NODUP;
|
||||
char *head_ref = NULL;
|
||||
int head_type;
|
||||
struct files_transaction_backend_data *backend_data;
|
||||
|
|
@ -2898,7 +2895,8 @@ static int files_transaction_prepare(struct ref_store *ref_store,
|
|||
struct ref_update *update = transaction->updates[i];
|
||||
|
||||
ret = lock_ref_for_update(refs, update, transaction,
|
||||
head_ref, &affected_refnames, err);
|
||||
head_ref, &refnames_to_check,
|
||||
&affected_refnames, err);
|
||||
if (ret)
|
||||
goto cleanup;
|
||||
|
||||
|
|
@ -2930,6 +2928,26 @@ static int files_transaction_prepare(struct ref_store *ref_store,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Verify that none of the loose reference that we're about to write
|
||||
* conflict with any existing packed references. Ideally, we'd do this
|
||||
* check after the packed-refs are locked so that the file cannot
|
||||
* change underneath our feet. But introducing such a lock now would
|
||||
* probably do more harm than good as users rely on there not being a
|
||||
* global lock with the "files" backend.
|
||||
*
|
||||
* Another alternative would be to do the check after the (optional)
|
||||
* lock, but that would extend the time we spend in the globally-locked
|
||||
* state.
|
||||
*
|
||||
* So instead, we accept the race for now.
|
||||
*/
|
||||
if (refs_verify_refnames_available(refs->packed_ref_store, &refnames_to_check,
|
||||
&affected_refnames, NULL, 0, err)) {
|
||||
ret = TRANSACTION_NAME_CONFLICT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (packed_transaction) {
|
||||
if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
|
||||
ret = TRANSACTION_GENERIC_ERROR;
|
||||
|
|
@ -2972,6 +2990,7 @@ static int files_transaction_prepare(struct ref_store *ref_store,
|
|||
cleanup:
|
||||
free(head_ref);
|
||||
string_list_clear(&affected_refnames, 0);
|
||||
string_list_clear(&refnames_to_check, 0);
|
||||
|
||||
if (ret)
|
||||
files_transaction_cleanup(refs, transaction);
|
||||
|
|
@ -3036,6 +3055,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
|
|||
size_t i;
|
||||
int ret = 0;
|
||||
struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
|
||||
struct string_list refnames_to_check = STRING_LIST_INIT_NODUP;
|
||||
struct ref_transaction *packed_transaction = NULL;
|
||||
struct ref_transaction *loose_transaction = NULL;
|
||||
|
||||
|
|
@ -3085,11 +3105,7 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
|
|||
!is_null_oid(&update->old_oid))
|
||||
BUG("initial ref transaction with old_sha1 set");
|
||||
|
||||
if (refs_verify_refname_available(&refs->base, update->refname,
|
||||
&affected_refnames, NULL, 1, err)) {
|
||||
ret = TRANSACTION_NAME_CONFLICT;
|
||||
goto cleanup;
|
||||
}
|
||||
string_list_append(&refnames_to_check, update->refname);
|
||||
|
||||
/*
|
||||
* packed-refs don't support symbolic refs, root refs and reflogs,
|
||||
|
|
@ -3125,8 +3141,19 @@ static int files_transaction_finish_initial(struct files_ref_store *refs,
|
|||
}
|
||||
}
|
||||
|
||||
if (packed_refs_lock(refs->packed_ref_store, 0, err) ||
|
||||
ref_transaction_commit(packed_transaction, err)) {
|
||||
if (packed_refs_lock(refs->packed_ref_store, 0, err)) {
|
||||
ret = TRANSACTION_GENERIC_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (refs_verify_refnames_available(&refs->base, &refnames_to_check,
|
||||
&affected_refnames, NULL, 1, err)) {
|
||||
packed_refs_unlock(refs->packed_ref_store);
|
||||
ret = TRANSACTION_NAME_CONFLICT;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (ref_transaction_commit(packed_transaction, err)) {
|
||||
ret = TRANSACTION_GENERIC_ERROR;
|
||||
goto cleanup;
|
||||
}
|
||||
|
|
@ -3147,6 +3174,7 @@ cleanup:
|
|||
ref_transaction_free(packed_transaction);
|
||||
transaction->state = REF_TRANSACTION_CLOSED;
|
||||
string_list_clear(&affected_refnames, 0);
|
||||
string_list_clear(&refnames_to_check, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -3808,6 +3836,7 @@ static int files_fsck_refs_dir(struct ref_store *ref_store,
|
|||
ret = error(_("failed to iterate over '%s'"), sb.buf);
|
||||
|
||||
out:
|
||||
dir_iterator_free(iter);
|
||||
strbuf_release(&sb);
|
||||
strbuf_release(&refname);
|
||||
return ret;
|
||||
|
|
|
|||
150
refs/iterator.c
150
refs/iterator.c
|
|
@ -15,15 +15,26 @@ int ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
return ref_iterator->vtable->advance(ref_iterator);
|
||||
}
|
||||
|
||||
int ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
return ref_iterator->vtable->seek(ref_iterator, prefix);
|
||||
}
|
||||
|
||||
int ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
return ref_iterator->vtable->peel(ref_iterator, peeled);
|
||||
}
|
||||
|
||||
int ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
void ref_iterator_free(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
return ref_iterator->vtable->abort(ref_iterator);
|
||||
if (ref_iterator) {
|
||||
ref_iterator->vtable->release(ref_iterator);
|
||||
/* Help make use-after-free bugs fail quickly: */
|
||||
ref_iterator->vtable = NULL;
|
||||
free(ref_iterator);
|
||||
}
|
||||
}
|
||||
|
||||
void base_ref_iterator_init(struct ref_iterator *iter,
|
||||
|
|
@ -36,20 +47,19 @@ void base_ref_iterator_init(struct ref_iterator *iter,
|
|||
iter->flags = 0;
|
||||
}
|
||||
|
||||
void base_ref_iterator_free(struct ref_iterator *iter)
|
||||
{
|
||||
/* Help make use-after-free bugs fail quickly: */
|
||||
iter->vtable = NULL;
|
||||
free(iter);
|
||||
}
|
||||
|
||||
struct empty_ref_iterator {
|
||||
struct ref_iterator base;
|
||||
};
|
||||
|
||||
static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
||||
static int empty_ref_iterator_advance(struct ref_iterator *ref_iterator UNUSED)
|
||||
{
|
||||
return ref_iterator_abort(ref_iterator);
|
||||
return ITER_DONE;
|
||||
}
|
||||
|
||||
static int empty_ref_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
|
||||
const char *prefix UNUSED)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
|
||||
|
|
@ -58,16 +68,15 @@ static int empty_ref_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
|
|||
BUG("peel called for empty iterator");
|
||||
}
|
||||
|
||||
static int empty_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void empty_ref_iterator_release(struct ref_iterator *ref_iterator UNUSED)
|
||||
{
|
||||
base_ref_iterator_free(ref_iterator);
|
||||
return ITER_DONE;
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable empty_ref_iterator_vtable = {
|
||||
.advance = empty_ref_iterator_advance,
|
||||
.seek = empty_ref_iterator_seek,
|
||||
.peel = empty_ref_iterator_peel,
|
||||
.abort = empty_ref_iterator_abort,
|
||||
.release = empty_ref_iterator_release,
|
||||
};
|
||||
|
||||
struct ref_iterator *empty_ref_iterator_begin(void)
|
||||
|
|
@ -87,7 +96,8 @@ int is_empty_ref_iterator(struct ref_iterator *ref_iterator)
|
|||
struct merge_ref_iterator {
|
||||
struct ref_iterator base;
|
||||
|
||||
struct ref_iterator *iter0, *iter1;
|
||||
struct ref_iterator *iter0, *iter0_owned;
|
||||
struct ref_iterator *iter1, *iter1_owned;
|
||||
|
||||
ref_iterator_select_fn *select;
|
||||
void *cb_data;
|
||||
|
|
@ -179,9 +189,8 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
iter->select(iter->iter0, iter->iter1, iter->cb_data);
|
||||
|
||||
if (selection == ITER_SELECT_DONE) {
|
||||
return ref_iterator_abort(ref_iterator);
|
||||
return ITER_DONE;
|
||||
} else if (selection == ITER_SELECT_ERROR) {
|
||||
ref_iterator_abort(ref_iterator);
|
||||
return ITER_ERROR;
|
||||
}
|
||||
|
||||
|
|
@ -211,10 +220,31 @@ static int merge_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
}
|
||||
|
||||
error:
|
||||
ref_iterator_abort(ref_iterator);
|
||||
return ITER_ERROR;
|
||||
}
|
||||
|
||||
static int merge_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct merge_ref_iterator *iter =
|
||||
(struct merge_ref_iterator *)ref_iterator;
|
||||
int ret;
|
||||
|
||||
iter->current = NULL;
|
||||
iter->iter0 = iter->iter0_owned;
|
||||
iter->iter1 = iter->iter1_owned;
|
||||
|
||||
ret = ref_iterator_seek(iter->iter0, prefix);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = ref_iterator_seek(iter->iter1, prefix);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
|
@ -227,28 +257,19 @@ static int merge_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
return ref_iterator_peel(*iter->current, peeled);
|
||||
}
|
||||
|
||||
static int merge_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void merge_ref_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct merge_ref_iterator *iter =
|
||||
(struct merge_ref_iterator *)ref_iterator;
|
||||
int ok = ITER_DONE;
|
||||
|
||||
if (iter->iter0) {
|
||||
if (ref_iterator_abort(iter->iter0) != ITER_DONE)
|
||||
ok = ITER_ERROR;
|
||||
}
|
||||
if (iter->iter1) {
|
||||
if (ref_iterator_abort(iter->iter1) != ITER_DONE)
|
||||
ok = ITER_ERROR;
|
||||
}
|
||||
base_ref_iterator_free(ref_iterator);
|
||||
return ok;
|
||||
ref_iterator_free(iter->iter0_owned);
|
||||
ref_iterator_free(iter->iter1_owned);
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable merge_ref_iterator_vtable = {
|
||||
.advance = merge_ref_iterator_advance,
|
||||
.seek = merge_ref_iterator_seek,
|
||||
.peel = merge_ref_iterator_peel,
|
||||
.abort = merge_ref_iterator_abort,
|
||||
.release = merge_ref_iterator_release,
|
||||
};
|
||||
|
||||
struct ref_iterator *merge_ref_iterator_begin(
|
||||
|
|
@ -267,8 +288,8 @@ struct ref_iterator *merge_ref_iterator_begin(
|
|||
*/
|
||||
|
||||
base_ref_iterator_init(ref_iterator, &merge_ref_iterator_vtable);
|
||||
iter->iter0 = iter0;
|
||||
iter->iter1 = iter1;
|
||||
iter->iter0 = iter->iter0_owned = iter0;
|
||||
iter->iter1 = iter->iter1_owned = iter1;
|
||||
iter->select = select;
|
||||
iter->cb_data = cb_data;
|
||||
iter->current = NULL;
|
||||
|
|
@ -310,10 +331,10 @@ struct ref_iterator *overlay_ref_iterator_begin(
|
|||
* them.
|
||||
*/
|
||||
if (is_empty_ref_iterator(front)) {
|
||||
ref_iterator_abort(front);
|
||||
ref_iterator_free(front);
|
||||
return back;
|
||||
} else if (is_empty_ref_iterator(back)) {
|
||||
ref_iterator_abort(back);
|
||||
ref_iterator_free(back);
|
||||
return front;
|
||||
}
|
||||
|
||||
|
|
@ -350,19 +371,15 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
|
||||
while ((ok = ref_iterator_advance(iter->iter0)) == ITER_OK) {
|
||||
int cmp = compare_prefix(iter->iter0->refname, iter->prefix);
|
||||
|
||||
if (cmp < 0)
|
||||
continue;
|
||||
|
||||
if (cmp > 0) {
|
||||
/*
|
||||
* As the source iterator is ordered, we
|
||||
* can stop the iteration as soon as we see a
|
||||
* refname that comes after the prefix:
|
||||
*/
|
||||
ok = ref_iterator_abort(iter->iter0);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* As the source iterator is ordered, we
|
||||
* can stop the iteration as soon as we see a
|
||||
* refname that comes after the prefix:
|
||||
*/
|
||||
if (cmp > 0)
|
||||
return ITER_DONE;
|
||||
|
||||
if (iter->trim) {
|
||||
/*
|
||||
|
|
@ -386,12 +403,19 @@ static int prefix_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
return ITER_OK;
|
||||
}
|
||||
|
||||
iter->iter0 = NULL;
|
||||
if (ref_iterator_abort(ref_iterator) != ITER_DONE)
|
||||
return ITER_ERROR;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int prefix_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct prefix_ref_iterator *iter =
|
||||
(struct prefix_ref_iterator *)ref_iterator;
|
||||
free(iter->prefix);
|
||||
iter->prefix = xstrdup_or_null(prefix);
|
||||
return ref_iterator_seek(iter->iter0, prefix);
|
||||
}
|
||||
|
||||
static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
|
@ -401,23 +425,19 @@ static int prefix_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
return ref_iterator_peel(iter->iter0, peeled);
|
||||
}
|
||||
|
||||
static int prefix_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void prefix_ref_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct prefix_ref_iterator *iter =
|
||||
(struct prefix_ref_iterator *)ref_iterator;
|
||||
int ok = ITER_DONE;
|
||||
|
||||
if (iter->iter0)
|
||||
ok = ref_iterator_abort(iter->iter0);
|
||||
ref_iterator_free(iter->iter0);
|
||||
free(iter->prefix);
|
||||
base_ref_iterator_free(ref_iterator);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable prefix_ref_iterator_vtable = {
|
||||
.advance = prefix_ref_iterator_advance,
|
||||
.seek = prefix_ref_iterator_seek,
|
||||
.peel = prefix_ref_iterator_peel,
|
||||
.abort = prefix_ref_iterator_abort,
|
||||
.release = prefix_ref_iterator_release,
|
||||
};
|
||||
|
||||
struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
|
||||
|
|
@ -453,20 +473,14 @@ int do_for_each_ref_iterator(struct ref_iterator *iter,
|
|||
current_ref_iter = iter;
|
||||
while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
|
||||
retval = fn(iter->refname, iter->referent, iter->oid, iter->flags, cb_data);
|
||||
if (retval) {
|
||||
/*
|
||||
* If ref_iterator_abort() returns ITER_ERROR,
|
||||
* we ignore that error in deference to the
|
||||
* callback function's return value.
|
||||
*/
|
||||
ref_iterator_abort(iter);
|
||||
if (retval)
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
out:
|
||||
current_ref_iter = old_ref_iter;
|
||||
if (ok == ITER_ERROR)
|
||||
return -1;
|
||||
retval = -1;
|
||||
ref_iterator_free(iter);
|
||||
return retval;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -819,6 +819,8 @@ struct packed_ref_iterator {
|
|||
|
||||
struct snapshot *snapshot;
|
||||
|
||||
char *prefix;
|
||||
|
||||
/* The current position in the snapshot's buffer: */
|
||||
const char *pos;
|
||||
|
||||
|
|
@ -841,11 +843,9 @@ struct packed_ref_iterator {
|
|||
};
|
||||
|
||||
/*
|
||||
* Move the iterator to the next record in the snapshot, without
|
||||
* respect for whether the record is actually required by the current
|
||||
* iteration. Adjust the fields in `iter` and return `ITER_OK` or
|
||||
* `ITER_DONE`. This function does not free the iterator in the case
|
||||
* of `ITER_DONE`.
|
||||
* Move the iterator to the next record in the snapshot. Adjust the fields in
|
||||
* `iter` and return `ITER_OK` or `ITER_DONE`. This function does not free the
|
||||
* iterator in the case of `ITER_DONE`.
|
||||
*/
|
||||
static int next_record(struct packed_ref_iterator *iter)
|
||||
{
|
||||
|
|
@ -942,6 +942,9 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
int ok;
|
||||
|
||||
while ((ok = next_record(iter)) == ITER_OK) {
|
||||
const char *refname = iter->base.refname;
|
||||
const char *prefix = iter->prefix;
|
||||
|
||||
if (iter->flags & DO_FOR_EACH_PER_WORKTREE_ONLY &&
|
||||
!is_per_worktree_ref(iter->base.refname))
|
||||
continue;
|
||||
|
|
@ -951,15 +954,41 @@ static int packed_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
&iter->oid, iter->flags))
|
||||
continue;
|
||||
|
||||
while (prefix && *prefix) {
|
||||
if (*refname < *prefix)
|
||||
BUG("packed-refs backend yielded reference preceding its prefix");
|
||||
else if (*refname > *prefix)
|
||||
return ITER_DONE;
|
||||
prefix++;
|
||||
refname++;
|
||||
}
|
||||
|
||||
return ITER_OK;
|
||||
}
|
||||
|
||||
if (ref_iterator_abort(ref_iterator) != ITER_DONE)
|
||||
ok = ITER_ERROR;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int packed_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct packed_ref_iterator *iter =
|
||||
(struct packed_ref_iterator *)ref_iterator;
|
||||
const char *start;
|
||||
|
||||
if (prefix && *prefix)
|
||||
start = find_reference_location(iter->snapshot, prefix, 0);
|
||||
else
|
||||
start = iter->snapshot->start;
|
||||
|
||||
free(iter->prefix);
|
||||
iter->prefix = xstrdup_or_null(prefix);
|
||||
iter->pos = start;
|
||||
iter->eof = iter->snapshot->eof;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
|
@ -976,23 +1005,21 @@ static int packed_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
}
|
||||
}
|
||||
|
||||
static int packed_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void packed_ref_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct packed_ref_iterator *iter =
|
||||
(struct packed_ref_iterator *)ref_iterator;
|
||||
int ok = ITER_DONE;
|
||||
|
||||
strbuf_release(&iter->refname_buf);
|
||||
free(iter->jump);
|
||||
free(iter->prefix);
|
||||
release_snapshot(iter->snapshot);
|
||||
base_ref_iterator_free(ref_iterator);
|
||||
return ok;
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable packed_ref_iterator_vtable = {
|
||||
.advance = packed_ref_iterator_advance,
|
||||
.seek = packed_ref_iterator_seek,
|
||||
.peel = packed_ref_iterator_peel,
|
||||
.abort = packed_ref_iterator_abort
|
||||
.release = packed_ref_iterator_release,
|
||||
};
|
||||
|
||||
static int jump_list_entry_cmp(const void *va, const void *vb)
|
||||
|
|
@ -1104,7 +1131,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
|
|||
{
|
||||
struct packed_ref_store *refs;
|
||||
struct snapshot *snapshot;
|
||||
const char *start;
|
||||
struct packed_ref_iterator *iter;
|
||||
struct ref_iterator *ref_iterator;
|
||||
unsigned int required_flags = REF_STORE_READ;
|
||||
|
|
@ -1120,14 +1146,6 @@ static struct ref_iterator *packed_ref_iterator_begin(
|
|||
*/
|
||||
snapshot = get_snapshot(refs);
|
||||
|
||||
if (prefix && *prefix)
|
||||
start = find_reference_location(snapshot, prefix, 0);
|
||||
else
|
||||
start = snapshot->start;
|
||||
|
||||
if (start == snapshot->eof)
|
||||
return empty_ref_iterator_begin();
|
||||
|
||||
CALLOC_ARRAY(iter, 1);
|
||||
ref_iterator = &iter->base;
|
||||
base_ref_iterator_init(ref_iterator, &packed_ref_iterator_vtable);
|
||||
|
|
@ -1137,19 +1155,15 @@ static struct ref_iterator *packed_ref_iterator_begin(
|
|||
|
||||
iter->snapshot = snapshot;
|
||||
acquire_snapshot(snapshot);
|
||||
|
||||
iter->pos = start;
|
||||
iter->eof = snapshot->eof;
|
||||
strbuf_init(&iter->refname_buf, 0);
|
||||
|
||||
iter->base.oid = &iter->oid;
|
||||
|
||||
iter->repo = ref_store->repo;
|
||||
iter->flags = flags;
|
||||
|
||||
if (prefix && *prefix)
|
||||
/* Stop iteration after we've gone *past* prefix: */
|
||||
ref_iterator = prefix_ref_iterator_begin(ref_iterator, prefix, 0);
|
||||
if (packed_ref_iterator_seek(&iter->base, prefix) < 0) {
|
||||
ref_iterator_free(&iter->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ref_iterator;
|
||||
}
|
||||
|
|
@ -1362,8 +1376,10 @@ static int write_with_updates(struct packed_ref_store *refs,
|
|||
*/
|
||||
iter = packed_ref_iterator_begin(&refs->base, "", NULL,
|
||||
DO_FOR_EACH_INCLUDE_BROKEN);
|
||||
if ((ok = ref_iterator_advance(iter)) != ITER_OK)
|
||||
if ((ok = ref_iterator_advance(iter)) != ITER_OK) {
|
||||
ref_iterator_free(iter);
|
||||
iter = NULL;
|
||||
}
|
||||
|
||||
i = 0;
|
||||
|
||||
|
|
@ -1411,8 +1427,10 @@ static int write_with_updates(struct packed_ref_store *refs,
|
|||
* the iterator over the unneeded
|
||||
* value.
|
||||
*/
|
||||
if ((ok = ref_iterator_advance(iter)) != ITER_OK)
|
||||
if ((ok = ref_iterator_advance(iter)) != ITER_OK) {
|
||||
ref_iterator_free(iter);
|
||||
iter = NULL;
|
||||
}
|
||||
cmp = +1;
|
||||
} else {
|
||||
/*
|
||||
|
|
@ -1449,8 +1467,10 @@ static int write_with_updates(struct packed_ref_store *refs,
|
|||
peel_error ? NULL : &peeled))
|
||||
goto write_error;
|
||||
|
||||
if ((ok = ref_iterator_advance(iter)) != ITER_OK)
|
||||
if ((ok = ref_iterator_advance(iter)) != ITER_OK) {
|
||||
ref_iterator_free(iter);
|
||||
iter = NULL;
|
||||
}
|
||||
} else if (is_null_oid(&update->new_oid)) {
|
||||
/*
|
||||
* The update wants to delete the reference,
|
||||
|
|
@ -1499,9 +1519,7 @@ write_error:
|
|||
get_tempfile_path(refs->tempfile), strerror(errno));
|
||||
|
||||
error:
|
||||
if (iter)
|
||||
ref_iterator_abort(iter);
|
||||
|
||||
ref_iterator_free(iter);
|
||||
delete_tempfile(&refs->tempfile);
|
||||
return -1;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -362,9 +362,7 @@ struct cache_ref_iterator {
|
|||
struct ref_iterator base;
|
||||
|
||||
/*
|
||||
* The number of levels currently on the stack. This is always
|
||||
* at least 1, because when it becomes zero the iteration is
|
||||
* ended and this struct is freed.
|
||||
* The number of levels currently on the stack.
|
||||
*/
|
||||
size_t levels_nr;
|
||||
|
||||
|
|
@ -376,7 +374,7 @@ struct cache_ref_iterator {
|
|||
* The prefix is matched textually, without regard for path
|
||||
* component boundaries.
|
||||
*/
|
||||
const char *prefix;
|
||||
char *prefix;
|
||||
|
||||
/*
|
||||
* A stack of levels. levels[0] is the uppermost level that is
|
||||
|
|
@ -389,6 +387,9 @@ struct cache_ref_iterator {
|
|||
struct cache_ref_iterator_level *levels;
|
||||
|
||||
struct repository *repo;
|
||||
struct ref_cache *cache;
|
||||
|
||||
int prime_dir;
|
||||
};
|
||||
|
||||
static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
||||
|
|
@ -396,6 +397,9 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
struct cache_ref_iterator *iter =
|
||||
(struct cache_ref_iterator *)ref_iterator;
|
||||
|
||||
if (!iter->levels_nr)
|
||||
return ITER_DONE;
|
||||
|
||||
while (1) {
|
||||
struct cache_ref_iterator_level *level =
|
||||
&iter->levels[iter->levels_nr - 1];
|
||||
|
|
@ -409,7 +413,7 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
if (++level->index == level->dir->nr) {
|
||||
/* This level is exhausted; pop up a level */
|
||||
if (--iter->levels_nr == 0)
|
||||
return ref_iterator_abort(ref_iterator);
|
||||
return ITER_DONE;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
|
@ -444,6 +448,41 @@ static int cache_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
}
|
||||
}
|
||||
|
||||
static int cache_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct cache_ref_iterator *iter =
|
||||
(struct cache_ref_iterator *)ref_iterator;
|
||||
struct cache_ref_iterator_level *level;
|
||||
struct ref_dir *dir;
|
||||
|
||||
dir = get_ref_dir(iter->cache->root);
|
||||
if (prefix && *prefix)
|
||||
dir = find_containing_dir(dir, prefix);
|
||||
if (!dir) {
|
||||
iter->levels_nr = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (iter->prime_dir)
|
||||
prime_ref_dir(dir, prefix);
|
||||
iter->levels_nr = 1;
|
||||
level = &iter->levels[0];
|
||||
level->index = -1;
|
||||
level->dir = dir;
|
||||
|
||||
if (prefix && *prefix) {
|
||||
free(iter->prefix);
|
||||
iter->prefix = xstrdup(prefix);
|
||||
level->prefix_state = PREFIX_WITHIN_DIR;
|
||||
} else {
|
||||
FREE_AND_NULL(iter->prefix);
|
||||
level->prefix_state = PREFIX_CONTAINS_DIR;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
|
@ -452,21 +491,19 @@ static int cache_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
return peel_object(iter->repo, ref_iterator->oid, peeled) ? -1 : 0;
|
||||
}
|
||||
|
||||
static int cache_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void cache_ref_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct cache_ref_iterator *iter =
|
||||
(struct cache_ref_iterator *)ref_iterator;
|
||||
|
||||
free((char *)iter->prefix);
|
||||
free(iter->prefix);
|
||||
free(iter->levels);
|
||||
base_ref_iterator_free(ref_iterator);
|
||||
return ITER_DONE;
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable cache_ref_iterator_vtable = {
|
||||
.advance = cache_ref_iterator_advance,
|
||||
.seek = cache_ref_iterator_seek,
|
||||
.peel = cache_ref_iterator_peel,
|
||||
.abort = cache_ref_iterator_abort
|
||||
.release = cache_ref_iterator_release,
|
||||
};
|
||||
|
||||
struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
|
||||
|
|
@ -474,39 +511,22 @@ struct ref_iterator *cache_ref_iterator_begin(struct ref_cache *cache,
|
|||
struct repository *repo,
|
||||
int prime_dir)
|
||||
{
|
||||
struct ref_dir *dir;
|
||||
struct cache_ref_iterator *iter;
|
||||
struct ref_iterator *ref_iterator;
|
||||
struct cache_ref_iterator_level *level;
|
||||
|
||||
dir = get_ref_dir(cache->root);
|
||||
if (prefix && *prefix)
|
||||
dir = find_containing_dir(dir, prefix);
|
||||
if (!dir)
|
||||
/* There's nothing to iterate over. */
|
||||
return empty_ref_iterator_begin();
|
||||
|
||||
if (prime_dir)
|
||||
prime_ref_dir(dir, prefix);
|
||||
|
||||
CALLOC_ARRAY(iter, 1);
|
||||
ref_iterator = &iter->base;
|
||||
base_ref_iterator_init(ref_iterator, &cache_ref_iterator_vtable);
|
||||
ALLOC_GROW(iter->levels, 10, iter->levels_alloc);
|
||||
|
||||
iter->levels_nr = 1;
|
||||
level = &iter->levels[0];
|
||||
level->index = -1;
|
||||
level->dir = dir;
|
||||
|
||||
if (prefix && *prefix) {
|
||||
iter->prefix = xstrdup(prefix);
|
||||
level->prefix_state = PREFIX_WITHIN_DIR;
|
||||
} else {
|
||||
level->prefix_state = PREFIX_CONTAINS_DIR;
|
||||
}
|
||||
|
||||
iter->repo = repo;
|
||||
iter->cache = cache;
|
||||
iter->prime_dir = prime_dir;
|
||||
|
||||
if (cache_ref_iterator_seek(&iter->base, prefix) < 0) {
|
||||
ref_iterator_free(&iter->base);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ref_iterator;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -273,11 +273,11 @@ enum do_for_each_ref_flags {
|
|||
* the next reference and returns ITER_OK. The data pointed at by
|
||||
* refname and oid belong to the iterator; if you want to retain them
|
||||
* after calling ref_iterator_advance() again or calling
|
||||
* ref_iterator_abort(), you must make a copy. When the iteration has
|
||||
* ref_iterator_free(), you must make a copy. When the iteration has
|
||||
* been exhausted, ref_iterator_advance() releases any resources
|
||||
* associated with the iteration, frees the ref_iterator object, and
|
||||
* returns ITER_DONE. If you want to abort the iteration early, call
|
||||
* ref_iterator_abort(), which also frees the ref_iterator object and
|
||||
* ref_iterator_free(), which also frees the ref_iterator object and
|
||||
* any associated resources. If there was an internal error advancing
|
||||
* to the next entry, ref_iterator_advance() aborts the iteration,
|
||||
* frees the ref_iterator, and returns ITER_ERROR.
|
||||
|
|
@ -293,7 +293,7 @@ enum do_for_each_ref_flags {
|
|||
*
|
||||
* while ((ok = ref_iterator_advance(iter)) == ITER_OK) {
|
||||
* if (want_to_stop_iteration()) {
|
||||
* ok = ref_iterator_abort(iter);
|
||||
* ok = ITER_DONE;
|
||||
* break;
|
||||
* }
|
||||
*
|
||||
|
|
@ -307,6 +307,7 @@ enum do_for_each_ref_flags {
|
|||
*
|
||||
* if (ok != ITER_DONE)
|
||||
* handle_error();
|
||||
* ref_iterator_free(iter);
|
||||
*/
|
||||
struct ref_iterator {
|
||||
struct ref_iterator_vtable *vtable;
|
||||
|
|
@ -326,6 +327,22 @@ struct ref_iterator {
|
|||
*/
|
||||
int ref_iterator_advance(struct ref_iterator *ref_iterator);
|
||||
|
||||
/*
|
||||
* Seek the iterator to the first reference with the given prefix.
|
||||
* The prefix is matched as a literal string, without regard for path
|
||||
* separators. If prefix is NULL or the empty string, seek the iterator to the
|
||||
* first reference again.
|
||||
*
|
||||
* This function is expected to behave as if a new ref iterator with the same
|
||||
* prefix had been created, but allows reuse of iterators and thus may allow
|
||||
* the backend to optimize. Parameters other than the prefix that have been
|
||||
* passed when creating the iterator will remain unchanged.
|
||||
*
|
||||
* Returns 0 on success, a negative error code otherwise.
|
||||
*/
|
||||
int ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix);
|
||||
|
||||
/*
|
||||
* If possible, peel the reference currently being viewed by the
|
||||
* iterator. Return 0 on success.
|
||||
|
|
@ -333,12 +350,8 @@ int ref_iterator_advance(struct ref_iterator *ref_iterator);
|
|||
int ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled);
|
||||
|
||||
/*
|
||||
* End the iteration before it has been exhausted, freeing the
|
||||
* reference iterator and any associated resources and returning
|
||||
* ITER_DONE. If the abort itself failed, return ITER_ERROR.
|
||||
*/
|
||||
int ref_iterator_abort(struct ref_iterator *ref_iterator);
|
||||
/* Free the reference iterator and any associated resources. */
|
||||
void ref_iterator_free(struct ref_iterator *ref_iterator);
|
||||
|
||||
/*
|
||||
* An iterator over nothing (its first ref_iterator_advance() call
|
||||
|
|
@ -438,13 +451,6 @@ struct ref_iterator *prefix_ref_iterator_begin(struct ref_iterator *iter0,
|
|||
void base_ref_iterator_init(struct ref_iterator *iter,
|
||||
struct ref_iterator_vtable *vtable);
|
||||
|
||||
/*
|
||||
* Base class destructor for ref_iterators. Destroy the ref_iterator
|
||||
* part of iter and shallow-free the object. This is meant to be
|
||||
* called only by the destructors of derived classes.
|
||||
*/
|
||||
void base_ref_iterator_free(struct ref_iterator *iter);
|
||||
|
||||
/* Virtual function declarations for ref_iterators: */
|
||||
|
||||
/*
|
||||
|
|
@ -455,6 +461,13 @@ void base_ref_iterator_free(struct ref_iterator *iter);
|
|||
*/
|
||||
typedef int ref_iterator_advance_fn(struct ref_iterator *ref_iterator);
|
||||
|
||||
/*
|
||||
* Seek the iterator to the first reference matching the given prefix. Should
|
||||
* behave the same as if a new iterator was created with the same prefix.
|
||||
*/
|
||||
typedef int ref_iterator_seek_fn(struct ref_iterator *ref_iterator,
|
||||
const char *prefix);
|
||||
|
||||
/*
|
||||
* Peels the current ref, returning 0 for success or -1 for failure.
|
||||
*/
|
||||
|
|
@ -463,15 +476,15 @@ typedef int ref_iterator_peel_fn(struct ref_iterator *ref_iterator,
|
|||
|
||||
/*
|
||||
* Implementations of this function should free any resources specific
|
||||
* to the derived class, then call base_ref_iterator_free() to clean
|
||||
* up and free the ref_iterator object.
|
||||
* to the derived class.
|
||||
*/
|
||||
typedef int ref_iterator_abort_fn(struct ref_iterator *ref_iterator);
|
||||
typedef void ref_iterator_release_fn(struct ref_iterator *ref_iterator);
|
||||
|
||||
struct ref_iterator_vtable {
|
||||
ref_iterator_advance_fn *advance;
|
||||
ref_iterator_seek_fn *seek;
|
||||
ref_iterator_peel_fn *peel;
|
||||
ref_iterator_abort_fn *abort;
|
||||
ref_iterator_release_fn *release;
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -547,7 +547,7 @@ struct reftable_ref_iterator {
|
|||
struct reftable_ref_record ref;
|
||||
struct object_id oid;
|
||||
|
||||
const char *prefix;
|
||||
char *prefix;
|
||||
size_t prefix_len;
|
||||
char **exclude_patterns;
|
||||
size_t exclude_patterns_index;
|
||||
|
|
@ -711,20 +711,27 @@ static int reftable_ref_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
break;
|
||||
}
|
||||
|
||||
if (iter->err > 0) {
|
||||
if (ref_iterator_abort(ref_iterator) != ITER_DONE)
|
||||
return ITER_ERROR;
|
||||
if (iter->err > 0)
|
||||
return ITER_DONE;
|
||||
}
|
||||
|
||||
if (iter->err < 0) {
|
||||
ref_iterator_abort(ref_iterator);
|
||||
if (iter->err < 0)
|
||||
return ITER_ERROR;
|
||||
}
|
||||
|
||||
return ITER_OK;
|
||||
}
|
||||
|
||||
static int reftable_ref_iterator_seek(struct ref_iterator *ref_iterator,
|
||||
const char *prefix)
|
||||
{
|
||||
struct reftable_ref_iterator *iter =
|
||||
(struct reftable_ref_iterator *)ref_iterator;
|
||||
|
||||
free(iter->prefix);
|
||||
iter->prefix = xstrdup_or_null(prefix);
|
||||
iter->prefix_len = prefix ? strlen(prefix) : 0;
|
||||
iter->err = reftable_iterator_seek_ref(&iter->iter, prefix);
|
||||
|
||||
return iter->err;
|
||||
}
|
||||
|
||||
static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
||||
struct object_id *peeled)
|
||||
{
|
||||
|
|
@ -740,7 +747,7 @@ static int reftable_ref_iterator_peel(struct ref_iterator *ref_iterator,
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void reftable_ref_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct reftable_ref_iterator *iter =
|
||||
(struct reftable_ref_iterator *)ref_iterator;
|
||||
|
|
@ -751,14 +758,14 @@ static int reftable_ref_iterator_abort(struct ref_iterator *ref_iterator)
|
|||
free(iter->exclude_patterns[i]);
|
||||
free(iter->exclude_patterns);
|
||||
}
|
||||
free(iter);
|
||||
return ITER_DONE;
|
||||
free(iter->prefix);
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable reftable_ref_iterator_vtable = {
|
||||
.advance = reftable_ref_iterator_advance,
|
||||
.seek = reftable_ref_iterator_seek,
|
||||
.peel = reftable_ref_iterator_peel,
|
||||
.abort = reftable_ref_iterator_abort
|
||||
.release = reftable_ref_iterator_release,
|
||||
};
|
||||
|
||||
static int qsort_strcmp(const void *va, const void *vb)
|
||||
|
|
@ -815,8 +822,6 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
|
|||
|
||||
iter = xcalloc(1, sizeof(*iter));
|
||||
base_ref_iterator_init(&iter->base, &reftable_ref_iterator_vtable);
|
||||
iter->prefix = prefix;
|
||||
iter->prefix_len = prefix ? strlen(prefix) : 0;
|
||||
iter->base.oid = &iter->oid;
|
||||
iter->flags = flags;
|
||||
iter->refs = refs;
|
||||
|
|
@ -830,8 +835,11 @@ static struct reftable_ref_iterator *ref_iterator_for_stack(struct reftable_ref_
|
|||
if (ret)
|
||||
goto done;
|
||||
|
||||
reftable_stack_init_ref_iterator(stack, &iter->iter);
|
||||
ret = reftable_iterator_seek_ref(&iter->iter, prefix);
|
||||
ret = reftable_stack_init_ref_iterator(stack, &iter->iter);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
ret = reftable_ref_iterator_seek(&iter->base, prefix);
|
||||
if (ret)
|
||||
goto done;
|
||||
|
||||
|
|
@ -1069,6 +1077,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
|
|||
reftable_be_downcast(ref_store, REF_STORE_WRITE|REF_STORE_MAIN, "ref_transaction_prepare");
|
||||
struct strbuf referent = STRBUF_INIT, head_referent = STRBUF_INIT;
|
||||
struct string_list affected_refnames = STRING_LIST_INIT_NODUP;
|
||||
struct string_list refnames_to_check = STRING_LIST_INIT_NODUP;
|
||||
struct reftable_transaction_data *tx_data = NULL;
|
||||
struct reftable_backend *be;
|
||||
struct object_id head_oid;
|
||||
|
|
@ -1224,12 +1233,7 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
|
|||
* can output a proper error message instead of failing
|
||||
* at a later point.
|
||||
*/
|
||||
ret = refs_verify_refname_available(ref_store, u->refname,
|
||||
&affected_refnames, NULL,
|
||||
transaction->flags & REF_TRANSACTION_FLAG_INITIAL,
|
||||
err);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
string_list_append(&refnames_to_check, u->refname);
|
||||
|
||||
/*
|
||||
* There is no need to write the reference deletion
|
||||
|
|
@ -1379,6 +1383,12 @@ static int reftable_be_transaction_prepare(struct ref_store *ref_store,
|
|||
}
|
||||
}
|
||||
|
||||
ret = refs_verify_refnames_available(ref_store, &refnames_to_check, &affected_refnames, NULL,
|
||||
transaction->flags & REF_TRANSACTION_FLAG_INITIAL,
|
||||
err);
|
||||
if (ret < 0)
|
||||
goto done;
|
||||
|
||||
transaction->backend_data = tx_data;
|
||||
transaction->state = REF_TRANSACTION_PREPARED;
|
||||
|
||||
|
|
@ -1394,6 +1404,7 @@ done:
|
|||
string_list_clear(&affected_refnames, 0);
|
||||
strbuf_release(&referent);
|
||||
strbuf_release(&head_referent);
|
||||
string_list_clear(&refnames_to_check, 0);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -2017,20 +2028,20 @@ static int reftable_reflog_iterator_advance(struct ref_iterator *ref_iterator)
|
|||
break;
|
||||
}
|
||||
|
||||
if (iter->err > 0) {
|
||||
if (ref_iterator_abort(ref_iterator) != ITER_DONE)
|
||||
return ITER_ERROR;
|
||||
if (iter->err > 0)
|
||||
return ITER_DONE;
|
||||
}
|
||||
|
||||
if (iter->err < 0) {
|
||||
ref_iterator_abort(ref_iterator);
|
||||
if (iter->err < 0)
|
||||
return ITER_ERROR;
|
||||
}
|
||||
|
||||
return ITER_OK;
|
||||
}
|
||||
|
||||
static int reftable_reflog_iterator_seek(struct ref_iterator *ref_iterator UNUSED,
|
||||
const char *prefix UNUSED)
|
||||
{
|
||||
BUG("reftable reflog iterator cannot be seeked");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSED,
|
||||
struct object_id *peeled UNUSED)
|
||||
{
|
||||
|
|
@ -2038,21 +2049,20 @@ static int reftable_reflog_iterator_peel(struct ref_iterator *ref_iterator UNUSE
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int reftable_reflog_iterator_abort(struct ref_iterator *ref_iterator)
|
||||
static void reftable_reflog_iterator_release(struct ref_iterator *ref_iterator)
|
||||
{
|
||||
struct reftable_reflog_iterator *iter =
|
||||
(struct reftable_reflog_iterator *)ref_iterator;
|
||||
reftable_log_record_release(&iter->log);
|
||||
reftable_iterator_destroy(&iter->iter);
|
||||
strbuf_release(&iter->last_name);
|
||||
free(iter);
|
||||
return ITER_DONE;
|
||||
}
|
||||
|
||||
static struct ref_iterator_vtable reftable_reflog_iterator_vtable = {
|
||||
.advance = reftable_reflog_iterator_advance,
|
||||
.seek = reftable_reflog_iterator_seek,
|
||||
.peel = reftable_reflog_iterator_peel,
|
||||
.abort = reftable_reflog_iterator_abort
|
||||
.release = reftable_reflog_iterator_release,
|
||||
};
|
||||
|
||||
static struct reftable_reflog_iterator *reflog_iterator_for_stack(struct reftable_ref_store *refs,
|
||||
|
|
|
|||
34
refspec.c
34
refspec.c
|
|
@ -269,28 +269,28 @@ void refspec_ref_prefixes(const struct refspec *rs,
|
|||
}
|
||||
}
|
||||
|
||||
int match_name_with_pattern(const char *key, const char *name,
|
||||
const char *value, char **result)
|
||||
int match_refname_with_pattern(const char *pattern, const char *refname,
|
||||
const char *replacement, char **result)
|
||||
{
|
||||
const char *kstar = strchr(key, '*');
|
||||
const char *kstar = strchr(pattern, '*');
|
||||
size_t klen;
|
||||
size_t ksuffixlen;
|
||||
size_t namelen;
|
||||
int ret;
|
||||
if (!kstar)
|
||||
die(_("key '%s' of pattern had no '*'"), key);
|
||||
klen = kstar - key;
|
||||
die(_("pattern '%s' has no '*'"), pattern);
|
||||
klen = kstar - pattern;
|
||||
ksuffixlen = strlen(kstar + 1);
|
||||
namelen = strlen(name);
|
||||
ret = !strncmp(name, key, klen) && namelen >= klen + ksuffixlen &&
|
||||
!memcmp(name + namelen - ksuffixlen, kstar + 1, ksuffixlen);
|
||||
if (ret && value) {
|
||||
namelen = strlen(refname);
|
||||
ret = !strncmp(refname, pattern, klen) && namelen >= klen + ksuffixlen &&
|
||||
!memcmp(refname + namelen - ksuffixlen, kstar + 1, ksuffixlen);
|
||||
if (ret && replacement) {
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
const char *vstar = strchr(value, '*');
|
||||
const char *vstar = strchr(replacement, '*');
|
||||
if (!vstar)
|
||||
die(_("value '%s' of pattern has no '*'"), value);
|
||||
strbuf_add(&sb, value, vstar - value);
|
||||
strbuf_add(&sb, name + klen, namelen - klen - ksuffixlen);
|
||||
die(_("replacement '%s' has no '*'"), replacement);
|
||||
strbuf_add(&sb, replacement, vstar - replacement);
|
||||
strbuf_add(&sb, refname + klen, namelen - klen - ksuffixlen);
|
||||
strbuf_addstr(&sb, vstar + 1);
|
||||
*result = strbuf_detach(&sb, NULL);
|
||||
}
|
||||
|
|
@ -301,7 +301,7 @@ static int refspec_match(const struct refspec_item *refspec,
|
|||
const char *name)
|
||||
{
|
||||
if (refspec->pattern)
|
||||
return match_name_with_pattern(refspec->src, name, NULL, NULL);
|
||||
return match_refname_with_pattern(refspec->src, name, NULL, NULL);
|
||||
|
||||
return !strcmp(refspec->src, name);
|
||||
}
|
||||
|
|
@ -352,7 +352,7 @@ static int refspec_find_negative_match(struct refspec *rs, struct refspec_item *
|
|||
const char *key = refspec->dst ? refspec->dst : refspec->src;
|
||||
const char *value = refspec->src;
|
||||
|
||||
if (match_name_with_pattern(key, needle, value, &expn_name))
|
||||
if (match_refname_with_pattern(key, needle, value, &expn_name))
|
||||
string_list_append_nodup(&reversed, expn_name);
|
||||
} else if (refspec->matching) {
|
||||
/* For the special matching refspec, any query should match */
|
||||
|
|
@ -397,7 +397,7 @@ void refspec_find_all_matches(struct refspec *rs,
|
|||
if (!refspec->dst || refspec->negative)
|
||||
continue;
|
||||
if (refspec->pattern) {
|
||||
if (match_name_with_pattern(key, needle, value, result))
|
||||
if (match_refname_with_pattern(key, needle, value, result))
|
||||
string_list_append_nodup(results, *result);
|
||||
} else if (!strcmp(needle, key)) {
|
||||
string_list_append(results, value);
|
||||
|
|
@ -426,7 +426,7 @@ int refspec_find_match(struct refspec *rs, struct refspec_item *query)
|
|||
if (!refspec->dst || refspec->negative)
|
||||
continue;
|
||||
if (refspec->pattern) {
|
||||
if (match_name_with_pattern(key, needle, value, result)) {
|
||||
if (match_refname_with_pattern(key, needle, value, result)) {
|
||||
query->force = refspec->force;
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -75,11 +75,12 @@ void refspec_ref_prefixes(const struct refspec *rs,
|
|||
int refname_matches_negative_refspec_item(const char *refname, struct refspec *rs);
|
||||
|
||||
/*
|
||||
* Checks whether a name matches a pattern and optionally generates a result.
|
||||
* Returns 1 if the name matches the pattern, 0 otherwise.
|
||||
* Checks if a refname matches a globbing refspec pattern.
|
||||
* If replacement is provided, computes the corresponding mapped refname.
|
||||
* Returns 1 if refname matches pattern, 0 otherwise.
|
||||
*/
|
||||
int match_name_with_pattern(const char *key, const char *name,
|
||||
const char *value, char **result);
|
||||
int match_refname_with_pattern(const char *pattern, const char *refname,
|
||||
const char *replacement, char **result);
|
||||
|
||||
/*
|
||||
* Queries a refspec for a match and updates the query item.
|
||||
|
|
|
|||
6
remote.c
6
remote.c
|
|
@ -1322,9 +1322,9 @@ static char *get_ref_match(const struct refspec *rs, const struct ref *ref,
|
|||
const char *dst_side = item->dst ? item->dst : item->src;
|
||||
int match;
|
||||
if (direction == FROM_SRC)
|
||||
match = match_name_with_pattern(item->src, ref->name, dst_side, &name);
|
||||
match = match_refname_with_pattern(item->src, ref->name, dst_side, &name);
|
||||
else
|
||||
match = match_name_with_pattern(dst_side, ref->name, item->src, &name);
|
||||
match = match_refname_with_pattern(dst_side, ref->name, item->src, &name);
|
||||
if (match) {
|
||||
matching_refs = i;
|
||||
break;
|
||||
|
|
@ -1942,7 +1942,7 @@ static struct ref *get_expanded_map(const struct ref *remote_refs,
|
|||
|
||||
if (strchr(ref->name, '^'))
|
||||
continue; /* a dereference item */
|
||||
if (match_name_with_pattern(refspec->src, ref->name,
|
||||
if (match_refname_with_pattern(refspec->src, ref->name,
|
||||
refspec->dst, &expn_name) &&
|
||||
!ignore_symref_update(expn_name, &scratch)) {
|
||||
struct ref *cpy = copy_ref(ref);
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ int cmd__dir_iterator(int argc, const char **argv)
|
|||
printf("(%s) [%s] %s\n", diter->relative_path, diter->basename,
|
||||
diter->path.buf);
|
||||
}
|
||||
dir_iterator_free(diter);
|
||||
|
||||
if (iter_status != ITER_DONE) {
|
||||
printf("dir_iterator_advance failure\n");
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
# Import tree-wide shared Makefile behavior and libraries
|
||||
include ../../shared.mak
|
||||
|
||||
|
|
@ -8,7 +11,7 @@ SHELL_PATH ?= $(SHELL)
|
|||
SHELL_PATH_SQ = $(subst ','\'',$(SHELL_PATH))
|
||||
T = $(sort $(wildcard i[0-9][0-9][0-9][0-9]-*.sh))
|
||||
|
||||
all: $(T)
|
||||
all:: $(T)
|
||||
|
||||
$(T):
|
||||
@echo "*** $@ ***"; '$(SHELL_PATH_SQ)' $@ $(GIT_TEST_OPTS)
|
||||
|
|
|
|||
|
|
@ -1,10 +1,13 @@
|
|||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
# Import tree-wide shared Makefile behavior and libraries
|
||||
include ../../shared.mak
|
||||
|
||||
-include ../../config.mak
|
||||
export GIT_TEST_OPTIONS
|
||||
|
||||
all: test-lint perf
|
||||
all:: test-lint perf
|
||||
|
||||
perf: pre-clean
|
||||
./run
|
||||
|
|
|
|||
|
|
@ -113,6 +113,18 @@ test_expect_success 'check-mailmap --stdin simple address: no mapping' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'check-mailmap name and address: mapping' '
|
||||
test_when_finished "rm .mailmap" &&
|
||||
cat >.mailmap <<-EOF &&
|
||||
Bug Reports <bugs-new@company.xx> Bugs <bugs@company.xx>
|
||||
EOF
|
||||
cat >expect <<-EOF &&
|
||||
<bugs@company.xx>
|
||||
EOF
|
||||
git check-mailmap "bugs@company.xx" >actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'No mailmap' '
|
||||
cat >expect <<-EOF &&
|
||||
$GIT_AUTHOR_NAME (1):
|
||||
|
|
|
|||
|
|
@ -93,6 +93,22 @@ test_expect_success 'usage: --no-pickaxe-regex' '
|
|||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'usage: -G and -S with empty argument' '
|
||||
cat >expect <<-\EOF &&
|
||||
error: -S requires a non-empty argument
|
||||
EOF
|
||||
|
||||
test_expect_code 129 git log -S "" 2>actual &&
|
||||
test_cmp expect actual &&
|
||||
|
||||
cat >expect <<-\EOF &&
|
||||
error: -G requires a non-empty argument
|
||||
EOF
|
||||
|
||||
test_expect_code 129 git log -G "" 2>actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_log expect_initial --grep initial
|
||||
test_log expect_nomatch --grep InItial
|
||||
test_log_icase expect_initial --grep InItial
|
||||
|
|
|
|||
|
|
@ -1,3 +1,6 @@
|
|||
# The default target of this Makefile is...
|
||||
all::
|
||||
|
||||
# Import tree-wide shared Makefile behavior and libraries
|
||||
include ../shared.mak
|
||||
|
||||
|
|
@ -23,7 +26,7 @@ PERL_PATH_SQ = $(subst ','\'',$(PERL_PATH))
|
|||
DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
|
||||
template_instdir_SQ = $(subst ','\'',$(template_instdir))
|
||||
|
||||
all: boilerplates.made custom
|
||||
all:: boilerplates.made custom
|
||||
|
||||
# Put templates that can be copied straight from the source
|
||||
# in a file direc--tory--file in the source. They will be
|
||||
|
|
|
|||
|
|
@ -19,7 +19,6 @@
|
|||
* Davide Libenzi <davidel@xmailserver.org>
|
||||
*
|
||||
*/
|
||||
#define DISABLE_SIGN_COMPARE_WARNINGS
|
||||
|
||||
#include "xinclude.h"
|
||||
|
||||
|
|
@ -1014,7 +1013,7 @@ static void xdl_mark_ignorable_lines(xdchange_t *xscr, xdfenv_t *xe, long flags)
|
|||
|
||||
static int record_matches_regex(xrecord_t *rec, xpparam_t const *xpp) {
|
||||
regmatch_t regmatch;
|
||||
int i;
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < xpp->ignore_regex_nr; i++)
|
||||
if (!regexec_buf(xpp->ignore_regex[i], rec->ptr, rec->size, 1,
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ xdchange_t *xdl_get_hunk(xdchange_t **xscr, xdemitconf_t const *xecfg)
|
|||
xdchange_t *xch, *xchp, *lxch;
|
||||
long max_common = 2 * xecfg->ctxlen + xecfg->interhunkctxlen;
|
||||
long max_ignorable = xecfg->ctxlen;
|
||||
unsigned long ignored = 0; /* number of ignored blank lines */
|
||||
long ignored = 0; /* number of ignored blank lines */
|
||||
|
||||
/* remove ignorable changes that are too far before other changes */
|
||||
for (xchp = *xscr; xchp && xchp->ignore; xchp = xchp->next) {
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ static int scanA(struct histindex *index, int line1, int count1)
|
|||
unsigned int chain_len;
|
||||
struct record **rec_chain, *rec;
|
||||
|
||||
for (ptr = LINE_END(1); line1 <= ptr; ptr--) {
|
||||
for (ptr = LINE_END(1); (unsigned int)line1 <= ptr; ptr--) {
|
||||
tbl_idx = TABLE_HASH(index, 1, ptr);
|
||||
rec_chain = index->records + tbl_idx;
|
||||
rec = *rec_chain;
|
||||
|
|
@ -181,14 +181,14 @@ static int try_lcs(struct histindex *index, struct region *lcs, int b_ptr,
|
|||
be = bs;
|
||||
rc = rec->cnt;
|
||||
|
||||
while (line1 < as && line2 < bs
|
||||
while ((unsigned int)line1 < as && (unsigned int)line2 < bs
|
||||
&& CMP(index, 1, as - 1, 2, bs - 1)) {
|
||||
as--;
|
||||
bs--;
|
||||
if (1 < rc)
|
||||
rc = XDL_MIN(rc, CNT(index, as));
|
||||
}
|
||||
while (ae < LINE_END(1) && be < LINE_END(2)
|
||||
while (ae < (unsigned int)LINE_END(1) && be < (unsigned int)LINE_END(2)
|
||||
&& CMP(index, 1, ae + 1, 2, be + 1)) {
|
||||
ae++;
|
||||
be++;
|
||||
|
|
@ -313,7 +313,7 @@ redo:
|
|||
if (count1 <= 0 && count2 <= 0)
|
||||
return 0;
|
||||
|
||||
if (LINE_END(1) >= MAX_PTR)
|
||||
if ((unsigned int)LINE_END(1) >= MAX_PTR)
|
||||
return -1;
|
||||
|
||||
if (!count1) {
|
||||
|
|
|
|||
|
|
@ -23,8 +23,6 @@
|
|||
#if !defined(XINCLUDE_H)
|
||||
#define XINCLUDE_H
|
||||
|
||||
#define DISABLE_SIGN_COMPARE_WARNINGS
|
||||
|
||||
#include "git-compat-util.h"
|
||||
#include "xmacros.h"
|
||||
#include "xdiff.h"
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
* Davide Libenzi <davidel@xmailserver.org>
|
||||
*
|
||||
*/
|
||||
|
||||
#include "xinclude.h"
|
||||
|
||||
/*
|
||||
|
|
@ -75,7 +76,7 @@ struct hashmap {
|
|||
|
||||
static int is_anchor(xpparam_t const *xpp, const char *line)
|
||||
{
|
||||
int i;
|
||||
size_t i;
|
||||
for (i = 0; i < xpp->anchors_nr; i++) {
|
||||
if (!strncmp(line, xpp->anchors[i], strlen(xpp->anchors[i])))
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -375,7 +375,7 @@ static int xdl_format_hunk_hdr(long s1, long c1, long s2, long c2,
|
|||
nb += 3;
|
||||
if (func && funclen) {
|
||||
buf[nb++] = ' ';
|
||||
if (funclen > sizeof(buf) - nb - 1)
|
||||
if ((size_t)funclen > sizeof(buf) - nb - 1)
|
||||
funclen = sizeof(buf) - nb - 1;
|
||||
memcpy(buf + nb, func, funclen);
|
||||
nb += funclen;
|
||||
|
|
@ -437,7 +437,7 @@ void* xdl_alloc_grow_helper(void *p, long nr, long *alloc, size_t size)
|
|||
{
|
||||
void *tmp = NULL;
|
||||
size_t n = ((LONG_MAX - 16) / 2 >= *alloc) ? 2 * *alloc + 16 : LONG_MAX;
|
||||
if (nr > n)
|
||||
if ((size_t)nr > n)
|
||||
n = nr;
|
||||
if (SIZE_MAX / size >= n)
|
||||
tmp = xdl_realloc(p, n * size);
|
||||
|
|
|
|||
Loading…
Reference in New Issue