mirror of
https://github.com/git/git.git
synced 2024-11-23 09:56:28 +08:00
Merge branch 'fixes/2.45.1/2.40' into fixes/2.45.1/2.41
* fixes/2.45.1/2.40: Revert "fsck: warn about symlink pointing inside a gitdir" Revert "Add a helper function to compare file contents" clone: drop the protections where hooks aren't run tests: verify that `clone -c core.hooksPath=/dev/null` works again Revert "core.hooksPath: add some protection while cloning" init: use the correct path of the templates directory again hook: plug a new memory leak ci: stop installing "gcc-13" for osx-gcc ci: avoid bare "gcc" for osx-gcc job ci: drop mention of BREW_INSTALL_PACKAGES variable send-email: avoid creating more than one Term::ReadLine object send-email: drop FakeTerm hack
This commit is contained in:
commit
4f215d214f
3
.github/workflows/main.yml
vendored
3
.github/workflows/main.yml
vendored
@ -264,8 +264,7 @@ jobs:
|
|||||||
cc: clang
|
cc: clang
|
||||||
pool: macos-13
|
pool: macos-13
|
||||||
- jobname: osx-gcc
|
- jobname: osx-gcc
|
||||||
cc: gcc
|
cc: gcc-13
|
||||||
cc_package: gcc-13
|
|
||||||
pool: macos-13
|
pool: macos-13
|
||||||
- jobname: linux-gcc-default
|
- jobname: linux-gcc-default
|
||||||
cc: gcc
|
cc: gcc
|
||||||
|
@ -157,18 +157,6 @@
|
|||||||
`nullSha1`::
|
`nullSha1`::
|
||||||
(WARN) Tree contains entries pointing to a null sha1.
|
(WARN) Tree contains entries pointing to a null sha1.
|
||||||
|
|
||||||
`symlinkPointsToGitDir`::
|
|
||||||
(WARN) Symbolic link points inside a gitdir.
|
|
||||||
|
|
||||||
`symlinkTargetBlob`::
|
|
||||||
(ERROR) A non-blob found instead of a symbolic link's target.
|
|
||||||
|
|
||||||
`symlinkTargetLength`::
|
|
||||||
(WARN) Symbolic link target longer than maximum path length.
|
|
||||||
|
|
||||||
`symlinkTargetMissing`::
|
|
||||||
(ERROR) Unable to read symbolic link target's blob.
|
|
||||||
|
|
||||||
`treeNotSorted`::
|
`treeNotSorted`::
|
||||||
(ERROR) A tree is not properly sorted.
|
(ERROR) A tree is not properly sorted.
|
||||||
|
|
||||||
|
2
Makefile
2
Makefile
@ -2743,7 +2743,7 @@ exec-cmd.sp exec-cmd.s exec-cmd.o: EXTRA_CPPFLAGS = \
|
|||||||
'-DFALLBACK_RUNTIME_PREFIX="$(prefix_SQ)"'
|
'-DFALLBACK_RUNTIME_PREFIX="$(prefix_SQ)"'
|
||||||
|
|
||||||
builtin/init-db.sp builtin/init-db.s builtin/init-db.o: GIT-PREFIX
|
builtin/init-db.sp builtin/init-db.s builtin/init-db.o: GIT-PREFIX
|
||||||
builtin/init-db.sp builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \
|
setup.sp setup.s setup.o: EXTRA_CPPFLAGS = \
|
||||||
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
|
-DDEFAULT_GIT_TEMPLATE_DIR='"$(template_dir_SQ)"'
|
||||||
|
|
||||||
config.sp config.s config.o: GIT-PREFIX
|
config.sp config.s config.o: GIT-PREFIX
|
||||||
|
@ -959,8 +959,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
int submodule_progress;
|
int submodule_progress;
|
||||||
int filter_submodules = 0;
|
int filter_submodules = 0;
|
||||||
int hash_algo;
|
int hash_algo;
|
||||||
const char *template_dir;
|
|
||||||
char *template_dir_dup = NULL;
|
|
||||||
|
|
||||||
struct transport_ls_refs_options transport_ls_refs_options =
|
struct transport_ls_refs_options transport_ls_refs_options =
|
||||||
TRANSPORT_LS_REFS_OPTIONS_INIT;
|
TRANSPORT_LS_REFS_OPTIONS_INIT;
|
||||||
@ -980,13 +978,6 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
usage_msg_opt(_("You must specify a repository to clone."),
|
usage_msg_opt(_("You must specify a repository to clone."),
|
||||||
builtin_clone_usage, builtin_clone_options);
|
builtin_clone_usage, builtin_clone_options);
|
||||||
|
|
||||||
xsetenv("GIT_CLONE_PROTECTION_ACTIVE", "true", 0 /* allow user override */);
|
|
||||||
template_dir = get_template_dir(option_template);
|
|
||||||
if (*template_dir && !is_absolute_path(template_dir))
|
|
||||||
template_dir = template_dir_dup =
|
|
||||||
absolute_pathdup(template_dir);
|
|
||||||
xsetenv("GIT_CLONE_TEMPLATE_DIR", template_dir, 1);
|
|
||||||
|
|
||||||
if (option_depth || option_since || option_not.nr)
|
if (option_depth || option_since || option_not.nr)
|
||||||
deepen = 1;
|
deepen = 1;
|
||||||
if (option_single_branch == -1)
|
if (option_single_branch == -1)
|
||||||
@ -1134,7 +1125,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
init_db(git_dir, real_git_dir, template_dir, GIT_HASH_UNKNOWN, NULL,
|
init_db(git_dir, real_git_dir, option_template, GIT_HASH_UNKNOWN, NULL,
|
||||||
INIT_DB_QUIET);
|
INIT_DB_QUIET);
|
||||||
|
|
||||||
if (real_git_dir) {
|
if (real_git_dir) {
|
||||||
@ -1478,7 +1469,7 @@ int cmd_clone(int argc, const char **argv, const char *prefix)
|
|||||||
free(dir);
|
free(dir);
|
||||||
free(path);
|
free(path);
|
||||||
free(repo_to_free);
|
free(repo_to_free);
|
||||||
free(template_dir_dup);
|
UNLEAK(repo);
|
||||||
junk_mode = JUNK_LEAVE_ALL;
|
junk_mode = JUNK_LEAVE_ALL;
|
||||||
|
|
||||||
transport_ls_refs_options_release(&transport_ls_refs_options);
|
transport_ls_refs_options_release(&transport_ls_refs_options);
|
||||||
|
@ -34,8 +34,6 @@ macos-*)
|
|||||||
export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1
|
export HOMEBREW_NO_AUTO_UPDATE=1 HOMEBREW_NO_INSTALL_CLEANUP=1
|
||||||
# Uncomment this if you want to run perf tests:
|
# Uncomment this if you want to run perf tests:
|
||||||
# brew install gnu-time
|
# brew install gnu-time
|
||||||
test -z "$BREW_INSTALL_PACKAGES" ||
|
|
||||||
brew install $BREW_INSTALL_PACKAGES
|
|
||||||
brew link --force gettext
|
brew link --force gettext
|
||||||
mkdir -p $HOME/bin
|
mkdir -p $HOME/bin
|
||||||
(
|
(
|
||||||
|
13
config.c
13
config.c
@ -1596,19 +1596,8 @@ static int git_default_core_config(const char *var, const char *value, void *cb)
|
|||||||
if (!strcmp(var, "core.attributesfile"))
|
if (!strcmp(var, "core.attributesfile"))
|
||||||
return git_config_pathname(&git_attributes_file, var, value);
|
return git_config_pathname(&git_attributes_file, var, value);
|
||||||
|
|
||||||
if (!strcmp(var, "core.hookspath")) {
|
if (!strcmp(var, "core.hookspath"))
|
||||||
if (current_config_scope() == CONFIG_SCOPE_LOCAL &&
|
|
||||||
git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0))
|
|
||||||
die(_("active `core.hooksPath` found in the local "
|
|
||||||
"repository config:\n\t%s\nFor security "
|
|
||||||
"reasons, this is disallowed by default.\nIf "
|
|
||||||
"this is intentional and the hook should "
|
|
||||||
"actually be run, please\nrun the command "
|
|
||||||
"again with "
|
|
||||||
"`GIT_CLONE_PROTECTION_ACTIVE=false`"),
|
|
||||||
value);
|
|
||||||
return git_config_pathname(&git_hooks_path, var, value);
|
return git_config_pathname(&git_hooks_path, var, value);
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(var, "core.bare")) {
|
if (!strcmp(var, "core.bare")) {
|
||||||
is_bare_repository_cfg = git_config_bool(var, value);
|
is_bare_repository_cfg = git_config_bool(var, value);
|
||||||
|
58
copy.c
58
copy.c
@ -71,61 +71,3 @@ int copy_file_with_time(const char *dst, const char *src, int mode)
|
|||||||
return copy_times(dst, src);
|
return copy_times(dst, src);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_symlinks_match(const char *path1, const char *path2)
|
|
||||||
{
|
|
||||||
struct strbuf buf1 = STRBUF_INIT, buf2 = STRBUF_INIT;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
if (!strbuf_readlink(&buf1, path1, 0) &&
|
|
||||||
!strbuf_readlink(&buf2, path2, 0))
|
|
||||||
ret = !strcmp(buf1.buf, buf2.buf);
|
|
||||||
|
|
||||||
strbuf_release(&buf1);
|
|
||||||
strbuf_release(&buf2);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
int do_files_match(const char *path1, const char *path2)
|
|
||||||
{
|
|
||||||
struct stat st1, st2;
|
|
||||||
int fd1 = -1, fd2 = -1, ret = 1;
|
|
||||||
char buf1[8192], buf2[8192];
|
|
||||||
|
|
||||||
if ((fd1 = open_nofollow(path1, O_RDONLY)) < 0 ||
|
|
||||||
fstat(fd1, &st1) || !S_ISREG(st1.st_mode)) {
|
|
||||||
if (fd1 < 0 && errno == ELOOP)
|
|
||||||
/* maybe this is a symbolic link? */
|
|
||||||
return do_symlinks_match(path1, path2);
|
|
||||||
ret = 0;
|
|
||||||
} else if ((fd2 = open_nofollow(path2, O_RDONLY)) < 0 ||
|
|
||||||
fstat(fd2, &st2) || !S_ISREG(st2.st_mode)) {
|
|
||||||
ret = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
/* to match, neither must be executable, or both */
|
|
||||||
ret = !(st1.st_mode & 0111) == !(st2.st_mode & 0111);
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
ret = st1.st_size == st2.st_size;
|
|
||||||
|
|
||||||
while (ret) {
|
|
||||||
ssize_t len1 = read_in_full(fd1, buf1, sizeof(buf1));
|
|
||||||
ssize_t len2 = read_in_full(fd2, buf2, sizeof(buf2));
|
|
||||||
|
|
||||||
if (len1 < 0 || len2 < 0 || len1 != len2)
|
|
||||||
ret = 0; /* read error or different file size */
|
|
||||||
else if (!len1) /* len2 is also 0; hit EOF on both */
|
|
||||||
break; /* ret is still true */
|
|
||||||
else
|
|
||||||
ret = !memcmp(buf1, buf2, len1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fd1 >= 0)
|
|
||||||
close(fd1);
|
|
||||||
if (fd2 >= 0)
|
|
||||||
close(fd2);
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
14
copy.h
14
copy.h
@ -7,18 +7,4 @@ int copy_fd(int ifd, int ofd);
|
|||||||
int copy_file(const char *dst, const char *src, int mode);
|
int copy_file(const char *dst, const char *src, int mode);
|
||||||
int copy_file_with_time(const char *dst, const char *src, int mode);
|
int copy_file_with_time(const char *dst, const char *src, int mode);
|
||||||
|
|
||||||
/*
|
|
||||||
* Compare the file mode and contents of two given files.
|
|
||||||
*
|
|
||||||
* If both files are actually symbolic links, the function returns 1 if the link
|
|
||||||
* targets are identical or 0 if they are not.
|
|
||||||
*
|
|
||||||
* If any of the two files cannot be accessed or in case of read failures, this
|
|
||||||
* function returns 0.
|
|
||||||
*
|
|
||||||
* If the file modes and contents are identical, the function returns 1,
|
|
||||||
* otherwise it returns 0.
|
|
||||||
*/
|
|
||||||
int do_files_match(const char *path1, const char *path2);
|
|
||||||
|
|
||||||
#endif /* COPY_H */
|
#endif /* COPY_H */
|
||||||
|
56
fsck.c
56
fsck.c
@ -639,8 +639,6 @@ static int fsck_tree(const struct object_id *tree_oid,
|
|||||||
retval += report(options, tree_oid, OBJ_TREE,
|
retval += report(options, tree_oid, OBJ_TREE,
|
||||||
FSCK_MSG_MAILMAP_SYMLINK,
|
FSCK_MSG_MAILMAP_SYMLINK,
|
||||||
".mailmap is a symlink");
|
".mailmap is a symlink");
|
||||||
oidset_insert(&options->symlink_targets_found,
|
|
||||||
entry_oid);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((backslash = strchr(name, '\\'))) {
|
if ((backslash = strchr(name, '\\'))) {
|
||||||
@ -1274,56 +1272,6 @@ static int fsck_blob(const struct object_id *oid, const char *buf,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oidset_contains(&options->symlink_targets_found, oid)) {
|
|
||||||
const char *ptr = buf;
|
|
||||||
const struct object_id *reported = NULL;
|
|
||||||
|
|
||||||
oidset_insert(&options->symlink_targets_done, oid);
|
|
||||||
|
|
||||||
if (!buf || size > PATH_MAX) {
|
|
||||||
/*
|
|
||||||
* A missing buffer here is a sign that the caller found the
|
|
||||||
* blob too gigantic to load into memory. Let's just consider
|
|
||||||
* that an error.
|
|
||||||
*/
|
|
||||||
return report(options, oid, OBJ_BLOB,
|
|
||||||
FSCK_MSG_SYMLINK_TARGET_LENGTH,
|
|
||||||
"symlink target too long");
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!reported && ptr) {
|
|
||||||
const char *p = ptr;
|
|
||||||
char c, *slash = strchrnul(ptr, '/');
|
|
||||||
char *backslash = memchr(ptr, '\\', slash - ptr);
|
|
||||||
|
|
||||||
c = *slash;
|
|
||||||
*slash = '\0';
|
|
||||||
|
|
||||||
while (!reported && backslash) {
|
|
||||||
*backslash = '\0';
|
|
||||||
if (is_ntfs_dotgit(p))
|
|
||||||
ret |= report(options, reported = oid, OBJ_BLOB,
|
|
||||||
FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR,
|
|
||||||
"symlink target points to git dir");
|
|
||||||
*backslash = '\\';
|
|
||||||
p = backslash + 1;
|
|
||||||
backslash = memchr(p, '\\', slash - p);
|
|
||||||
}
|
|
||||||
if (!reported && is_ntfs_dotgit(p))
|
|
||||||
ret |= report(options, reported = oid, OBJ_BLOB,
|
|
||||||
FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR,
|
|
||||||
"symlink target points to git dir");
|
|
||||||
|
|
||||||
if (!reported && is_hfs_dotgit(ptr))
|
|
||||||
ret |= report(options, reported = oid, OBJ_BLOB,
|
|
||||||
FSCK_MSG_SYMLINK_POINTS_TO_GIT_DIR,
|
|
||||||
"symlink target points to git dir");
|
|
||||||
|
|
||||||
*slash = c;
|
|
||||||
ptr = c ? slash + 1 : NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1422,10 +1370,6 @@ int fsck_finish(struct fsck_options *options)
|
|||||||
FSCK_MSG_GITATTRIBUTES_MISSING, FSCK_MSG_GITATTRIBUTES_BLOB,
|
FSCK_MSG_GITATTRIBUTES_MISSING, FSCK_MSG_GITATTRIBUTES_BLOB,
|
||||||
options, ".gitattributes");
|
options, ".gitattributes");
|
||||||
|
|
||||||
ret |= fsck_blobs(&options->symlink_targets_found, &options->symlink_targets_done,
|
|
||||||
FSCK_MSG_SYMLINK_TARGET_MISSING, FSCK_MSG_SYMLINK_TARGET_BLOB,
|
|
||||||
options, "<symlink-target>");
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
12
fsck.h
12
fsck.h
@ -64,8 +64,6 @@ enum fsck_msg_type {
|
|||||||
FUNC(GITATTRIBUTES_LARGE, ERROR) \
|
FUNC(GITATTRIBUTES_LARGE, ERROR) \
|
||||||
FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \
|
FUNC(GITATTRIBUTES_LINE_LENGTH, ERROR) \
|
||||||
FUNC(GITATTRIBUTES_BLOB, ERROR) \
|
FUNC(GITATTRIBUTES_BLOB, ERROR) \
|
||||||
FUNC(SYMLINK_TARGET_MISSING, ERROR) \
|
|
||||||
FUNC(SYMLINK_TARGET_BLOB, ERROR) \
|
|
||||||
/* warnings */ \
|
/* warnings */ \
|
||||||
FUNC(EMPTY_NAME, WARN) \
|
FUNC(EMPTY_NAME, WARN) \
|
||||||
FUNC(FULL_PATHNAME, WARN) \
|
FUNC(FULL_PATHNAME, WARN) \
|
||||||
@ -75,8 +73,6 @@ enum fsck_msg_type {
|
|||||||
FUNC(NULL_SHA1, WARN) \
|
FUNC(NULL_SHA1, WARN) \
|
||||||
FUNC(ZERO_PADDED_FILEMODE, WARN) \
|
FUNC(ZERO_PADDED_FILEMODE, WARN) \
|
||||||
FUNC(NUL_IN_COMMIT, WARN) \
|
FUNC(NUL_IN_COMMIT, WARN) \
|
||||||
FUNC(SYMLINK_TARGET_LENGTH, WARN) \
|
|
||||||
FUNC(SYMLINK_POINTS_TO_GIT_DIR, WARN) \
|
|
||||||
/* infos (reported as warnings, but ignored by default) */ \
|
/* infos (reported as warnings, but ignored by default) */ \
|
||||||
FUNC(BAD_FILEMODE, INFO) \
|
FUNC(BAD_FILEMODE, INFO) \
|
||||||
FUNC(GITMODULES_PARSE, INFO) \
|
FUNC(GITMODULES_PARSE, INFO) \
|
||||||
@ -144,8 +140,6 @@ struct fsck_options {
|
|||||||
struct oidset gitmodules_done;
|
struct oidset gitmodules_done;
|
||||||
struct oidset gitattributes_found;
|
struct oidset gitattributes_found;
|
||||||
struct oidset gitattributes_done;
|
struct oidset gitattributes_done;
|
||||||
struct oidset symlink_targets_found;
|
|
||||||
struct oidset symlink_targets_done;
|
|
||||||
kh_oid_map_t *object_names;
|
kh_oid_map_t *object_names;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -155,8 +149,6 @@ struct fsck_options {
|
|||||||
.gitmodules_done = OIDSET_INIT, \
|
.gitmodules_done = OIDSET_INIT, \
|
||||||
.gitattributes_found = OIDSET_INIT, \
|
.gitattributes_found = OIDSET_INIT, \
|
||||||
.gitattributes_done = OIDSET_INIT, \
|
.gitattributes_done = OIDSET_INIT, \
|
||||||
.symlink_targets_found = OIDSET_INIT, \
|
|
||||||
.symlink_targets_done = OIDSET_INIT, \
|
|
||||||
.error_func = fsck_error_function \
|
.error_func = fsck_error_function \
|
||||||
}
|
}
|
||||||
#define FSCK_OPTIONS_STRICT { \
|
#define FSCK_OPTIONS_STRICT { \
|
||||||
@ -165,8 +157,6 @@ struct fsck_options {
|
|||||||
.gitmodules_done = OIDSET_INIT, \
|
.gitmodules_done = OIDSET_INIT, \
|
||||||
.gitattributes_found = OIDSET_INIT, \
|
.gitattributes_found = OIDSET_INIT, \
|
||||||
.gitattributes_done = OIDSET_INIT, \
|
.gitattributes_done = OIDSET_INIT, \
|
||||||
.symlink_targets_found = OIDSET_INIT, \
|
|
||||||
.symlink_targets_done = OIDSET_INIT, \
|
|
||||||
.error_func = fsck_error_function, \
|
.error_func = fsck_error_function, \
|
||||||
}
|
}
|
||||||
#define FSCK_OPTIONS_MISSING_GITMODULES { \
|
#define FSCK_OPTIONS_MISSING_GITMODULES { \
|
||||||
@ -175,8 +165,6 @@ struct fsck_options {
|
|||||||
.gitmodules_done = OIDSET_INIT, \
|
.gitmodules_done = OIDSET_INIT, \
|
||||||
.gitattributes_found = OIDSET_INIT, \
|
.gitattributes_found = OIDSET_INIT, \
|
||||||
.gitattributes_done = OIDSET_INIT, \
|
.gitattributes_done = OIDSET_INIT, \
|
||||||
.symlink_targets_found = OIDSET_INIT, \
|
|
||||||
.symlink_targets_done = OIDSET_INIT, \
|
|
||||||
.error_func = fsck_error_cb_print_missing_gitmodules, \
|
.error_func = fsck_error_cb_print_missing_gitmodules, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,18 +26,6 @@ use Git::I18N;
|
|||||||
|
|
||||||
Getopt::Long::Configure qw/ pass_through /;
|
Getopt::Long::Configure qw/ pass_through /;
|
||||||
|
|
||||||
package FakeTerm;
|
|
||||||
sub new {
|
|
||||||
my ($class, $reason) = @_;
|
|
||||||
return bless \$reason, shift;
|
|
||||||
}
|
|
||||||
sub readline {
|
|
||||||
my $self = shift;
|
|
||||||
die "Cannot use readline on FakeTerm: $$self";
|
|
||||||
}
|
|
||||||
package main;
|
|
||||||
|
|
||||||
|
|
||||||
sub usage {
|
sub usage {
|
||||||
print <<EOT;
|
print <<EOT;
|
||||||
git send-email' [<options>] <file|directory>
|
git send-email' [<options>] <file|directory>
|
||||||
@ -971,17 +959,19 @@ EOT3
|
|||||||
do_edit(@files);
|
do_edit(@files);
|
||||||
}
|
}
|
||||||
|
|
||||||
sub term {
|
{
|
||||||
my $term = eval {
|
# Only instantiate one $term per program run, since some
|
||||||
|
# Term::ReadLine providers refuse to create a second instance.
|
||||||
|
my $term;
|
||||||
|
sub term {
|
||||||
require Term::ReadLine;
|
require Term::ReadLine;
|
||||||
$ENV{"GIT_SEND_EMAIL_NOTTY"}
|
if (!defined $term) {
|
||||||
? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
|
$term = $ENV{"GIT_SEND_EMAIL_NOTTY"}
|
||||||
: Term::ReadLine->new('git-send-email');
|
? Term::ReadLine->new('git-send-email', \*STDIN, \*STDOUT)
|
||||||
};
|
: Term::ReadLine->new('git-send-email');
|
||||||
if ($@) {
|
}
|
||||||
$term = FakeTerm->new("$@: going non-interactive");
|
return $term;
|
||||||
}
|
}
|
||||||
return $term;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sub ask {
|
sub ask {
|
||||||
|
33
hook.c
33
hook.c
@ -8,31 +8,6 @@
|
|||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "setup.h"
|
#include "setup.h"
|
||||||
#include "copy.h"
|
|
||||||
|
|
||||||
static int identical_to_template_hook(const char *name, const char *path)
|
|
||||||
{
|
|
||||||
const char *env = getenv("GIT_CLONE_TEMPLATE_DIR");
|
|
||||||
const char *template_dir = get_template_dir(env && *env ? env : NULL);
|
|
||||||
struct strbuf template_path = STRBUF_INIT;
|
|
||||||
int found_template_hook, ret;
|
|
||||||
|
|
||||||
strbuf_addf(&template_path, "%s/hooks/%s", template_dir, name);
|
|
||||||
found_template_hook = access(template_path.buf, X_OK) >= 0;
|
|
||||||
#ifdef STRIP_EXTENSION
|
|
||||||
if (!found_template_hook) {
|
|
||||||
strbuf_addstr(&template_path, STRIP_EXTENSION);
|
|
||||||
found_template_hook = access(template_path.buf, X_OK) >= 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
if (!found_template_hook)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
ret = do_files_match(template_path.buf, path);
|
|
||||||
|
|
||||||
strbuf_release(&template_path);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *find_hook(const char *name)
|
const char *find_hook(const char *name)
|
||||||
{
|
{
|
||||||
@ -69,14 +44,6 @@ const char *find_hook(const char *name)
|
|||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (!git_hooks_path && git_env_bool("GIT_CLONE_PROTECTION_ACTIVE", 0) &&
|
|
||||||
!identical_to_template_hook(name, path.buf))
|
|
||||||
die(_("active `%s` hook found during `git clone`:\n\t%s\n"
|
|
||||||
"For security reasons, this is disallowed by default.\n"
|
|
||||||
"If this is intentional and the hook should actually "
|
|
||||||
"be run, please\nrun the command again with "
|
|
||||||
"`GIT_CLONE_PROTECTION_ACTIVE=false`"),
|
|
||||||
name, path.buf);
|
|
||||||
return path.buf;
|
return path.buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -501,16 +501,6 @@ int cmd__path_utils(int argc, const char **argv)
|
|||||||
return !!res;
|
return !!res;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 4 && !strcmp(argv[1], "do_files_match")) {
|
|
||||||
int ret = do_files_match(argv[2], argv[3]);
|
|
||||||
|
|
||||||
if (ret)
|
|
||||||
printf("equal\n");
|
|
||||||
else
|
|
||||||
printf("different\n");
|
|
||||||
return !ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
|
fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
|
||||||
argv[1] ? argv[1] : "(there was none)");
|
argv[1] ? argv[1] : "(there was none)");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -610,45 +610,4 @@ test_expect_success !VALGRIND,RUNTIME_PREFIX,CAN_EXEC_IN_PWD '%(prefix)/ works'
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'do_files_match()' '
|
|
||||||
test_seq 0 10 >0-10.txt &&
|
|
||||||
test_seq -1 10 >-1-10.txt &&
|
|
||||||
test_seq 1 10 >1-10.txt &&
|
|
||||||
test_seq 1 9 >1-9.txt &&
|
|
||||||
test_seq 0 8 >0-8.txt &&
|
|
||||||
|
|
||||||
test-tool path-utils do_files_match 0-10.txt 0-10.txt >out &&
|
|
||||||
|
|
||||||
assert_fails() {
|
|
||||||
test_must_fail \
|
|
||||||
test-tool path-utils do_files_match "$1" "$2" >out &&
|
|
||||||
grep different out
|
|
||||||
} &&
|
|
||||||
|
|
||||||
assert_fails 0-8.txt 1-9.txt &&
|
|
||||||
assert_fails -1-10.txt 0-10.txt &&
|
|
||||||
assert_fails 1-10.txt 1-9.txt &&
|
|
||||||
assert_fails 1-10.txt .git &&
|
|
||||||
assert_fails does-not-exist 1-10.txt &&
|
|
||||||
|
|
||||||
if test_have_prereq FILEMODE
|
|
||||||
then
|
|
||||||
cp 0-10.txt 0-10.x &&
|
|
||||||
chmod a+x 0-10.x &&
|
|
||||||
assert_fails 0-10.txt 0-10.x
|
|
||||||
fi &&
|
|
||||||
|
|
||||||
if test_have_prereq SYMLINKS
|
|
||||||
then
|
|
||||||
ln -sf 0-10.txt symlink &&
|
|
||||||
ln -s 0-10.txt another-symlink &&
|
|
||||||
ln -s over-the-ocean yet-another-symlink &&
|
|
||||||
ln -s "$PWD/0-10.txt" absolute-symlink &&
|
|
||||||
assert_fails 0-10.txt symlink &&
|
|
||||||
test-tool path-utils do_files_match symlink another-symlink &&
|
|
||||||
assert_fails symlink yet-another-symlink &&
|
|
||||||
assert_fails symlink absolute-symlink
|
|
||||||
fi
|
|
||||||
'
|
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -41,4 +41,11 @@ test_expect_success 'git rev-parse --git-path hooks' '
|
|||||||
test .git/custom-hooks/abc = "$(cat actual)"
|
test .git/custom-hooks/abc = "$(cat actual)"
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'core.hooksPath=/dev/null' '
|
||||||
|
git clone -c core.hooksPath=/dev/null . no-templates &&
|
||||||
|
value="$(git -C no-templates config --local core.hooksPath)" &&
|
||||||
|
# The Bash used by Git for Windows rewrites `/dev/null` to `nul`
|
||||||
|
{ test /dev/null = "$value" || test nul = "$value"; }
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -1050,41 +1050,4 @@ test_expect_success 'fsck reports problems in main index without filename' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'fsck warning on symlink target with excessive length' '
|
|
||||||
symlink_target=$(printf "pattern %032769d" 1 | git hash-object -w --stdin) &&
|
|
||||||
test_when_finished "remove_object $symlink_target" &&
|
|
||||||
tree=$(printf "120000 blob %s\t%s\n" $symlink_target symlink | git mktree) &&
|
|
||||||
test_when_finished "remove_object $tree" &&
|
|
||||||
cat >expected <<-EOF &&
|
|
||||||
warning in blob $symlink_target: symlinkTargetLength: symlink target too long
|
|
||||||
EOF
|
|
||||||
git fsck --no-dangling >actual 2>&1 &&
|
|
||||||
test_cmp expected actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'fsck warning on symlink target pointing inside git dir' '
|
|
||||||
gitdir=$(printf ".git" | git hash-object -w --stdin) &&
|
|
||||||
ntfs_gitdir=$(printf "GIT~1" | git hash-object -w --stdin) &&
|
|
||||||
hfs_gitdir=$(printf ".${u200c}git" | git hash-object -w --stdin) &&
|
|
||||||
inside_gitdir=$(printf "nested/.git/config" | git hash-object -w --stdin) &&
|
|
||||||
benign_target=$(printf "legit/config" | git hash-object -w --stdin) &&
|
|
||||||
tree=$(printf "120000 blob %s\t%s\n" \
|
|
||||||
$benign_target benign_target \
|
|
||||||
$gitdir gitdir \
|
|
||||||
$hfs_gitdir hfs_gitdir \
|
|
||||||
$inside_gitdir inside_gitdir \
|
|
||||||
$ntfs_gitdir ntfs_gitdir |
|
|
||||||
git mktree) &&
|
|
||||||
for o in $gitdir $ntfs_gitdir $hfs_gitdir $inside_gitdir $benign_target $tree
|
|
||||||
do
|
|
||||||
test_when_finished "remove_object $o" || return 1
|
|
||||||
done &&
|
|
||||||
printf "warning in blob %s: symlinkPointsToGitDir: symlink target points to git dir\n" \
|
|
||||||
$gitdir $hfs_gitdir $inside_gitdir $ntfs_gitdir |
|
|
||||||
sort >expected &&
|
|
||||||
git fsck --no-dangling >actual 2>&1 &&
|
|
||||||
sort actual >actual.sorted &&
|
|
||||||
test_cmp expected actual.sorted
|
|
||||||
'
|
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -195,19 +195,4 @@ test_expect_success 'stdin to hooks' '
|
|||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'clone protections' '
|
|
||||||
test_config core.hooksPath "$(pwd)/my-hooks" &&
|
|
||||||
mkdir -p my-hooks &&
|
|
||||||
write_script my-hooks/test-hook <<-\EOF &&
|
|
||||||
echo Hook ran $1
|
|
||||||
EOF
|
|
||||||
|
|
||||||
git hook run test-hook 2>err &&
|
|
||||||
grep "Hook ran" err &&
|
|
||||||
test_must_fail env GIT_CLONE_PROTECTION_ACTIVE=true \
|
|
||||||
git hook run test-hook 2>err &&
|
|
||||||
grep "active .core.hooksPath" err &&
|
|
||||||
! grep "Hook ran" err
|
|
||||||
'
|
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
@ -771,57 +771,6 @@ test_expect_success 'batch missing blob request does not inadvertently try to fe
|
|||||||
git clone --filter=blob:limit=0 "file://$(pwd)/server" client
|
git clone --filter=blob:limit=0 "file://$(pwd)/server" client
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'clone with init.templatedir runs hooks' '
|
|
||||||
git init tmpl/hooks &&
|
|
||||||
write_script tmpl/hooks/post-checkout <<-EOF &&
|
|
||||||
echo HOOK-RUN >&2
|
|
||||||
echo I was here >hook.run
|
|
||||||
EOF
|
|
||||||
git -C tmpl/hooks add . &&
|
|
||||||
test_tick &&
|
|
||||||
git -C tmpl/hooks commit -m post-checkout &&
|
|
||||||
|
|
||||||
test_when_finished "git config --global --unset init.templateDir || :" &&
|
|
||||||
test_when_finished "git config --unset init.templateDir || :" &&
|
|
||||||
(
|
|
||||||
sane_unset GIT_TEMPLATE_DIR &&
|
|
||||||
NO_SET_GIT_TEMPLATE_DIR=t &&
|
|
||||||
export NO_SET_GIT_TEMPLATE_DIR &&
|
|
||||||
|
|
||||||
git -c core.hooksPath="$(pwd)/tmpl/hooks" \
|
|
||||||
clone tmpl/hooks hook-run-hookspath 2>err &&
|
|
||||||
! grep "active .* hook found" err &&
|
|
||||||
test_path_is_file hook-run-hookspath/hook.run &&
|
|
||||||
|
|
||||||
git -c init.templateDir="$(pwd)/tmpl" \
|
|
||||||
clone tmpl/hooks hook-run-config 2>err &&
|
|
||||||
! grep "active .* hook found" err &&
|
|
||||||
test_path_is_file hook-run-config/hook.run &&
|
|
||||||
|
|
||||||
git clone --template=tmpl tmpl/hooks hook-run-option 2>err &&
|
|
||||||
! grep "active .* hook found" err &&
|
|
||||||
test_path_is_file hook-run-option/hook.run &&
|
|
||||||
|
|
||||||
git config --global init.templateDir "$(pwd)/tmpl" &&
|
|
||||||
git clone tmpl/hooks hook-run-global-config 2>err &&
|
|
||||||
git config --global --unset init.templateDir &&
|
|
||||||
! grep "active .* hook found" err &&
|
|
||||||
test_path_is_file hook-run-global-config/hook.run &&
|
|
||||||
|
|
||||||
# clone ignores local `init.templateDir`; need to create
|
|
||||||
# a new repository because we deleted `.git/` in the
|
|
||||||
# `setup` test case above
|
|
||||||
git init local-clone &&
|
|
||||||
cd local-clone &&
|
|
||||||
|
|
||||||
git config init.templateDir "$(pwd)/../tmpl" &&
|
|
||||||
git clone ../tmpl/hooks hook-run-local-config 2>err &&
|
|
||||||
git config --unset init.templateDir &&
|
|
||||||
! grep "active .* hook found" err &&
|
|
||||||
test_path_is_missing hook-run-local-config/hook.run
|
|
||||||
)
|
|
||||||
'
|
|
||||||
|
|
||||||
. "$TEST_DIRECTORY"/lib-httpd.sh
|
. "$TEST_DIRECTORY"/lib-httpd.sh
|
||||||
start_httpd
|
start_httpd
|
||||||
|
|
||||||
|
@ -337,13 +337,14 @@ test_expect_success $PREREQ 'Show all headers' '
|
|||||||
test_expect_success $PREREQ 'Prompting works' '
|
test_expect_success $PREREQ 'Prompting works' '
|
||||||
clean_fake_sendmail &&
|
clean_fake_sendmail &&
|
||||||
(echo "to@example.com" &&
|
(echo "to@example.com" &&
|
||||||
echo ""
|
echo "my-message-id@example.com"
|
||||||
) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
|
) | GIT_SEND_EMAIL_NOTTY=1 git send-email \
|
||||||
--smtp-server="$(pwd)/fake.sendmail" \
|
--smtp-server="$(pwd)/fake.sendmail" \
|
||||||
$patches \
|
$patches \
|
||||||
2>errors &&
|
2>errors &&
|
||||||
grep "^From: A U Thor <author@example.com>\$" msgtxt1 &&
|
grep "^From: A U Thor <author@example.com>\$" msgtxt1 &&
|
||||||
grep "^To: to@example.com\$" msgtxt1
|
grep "^To: to@example.com\$" msgtxt1 &&
|
||||||
|
grep "^In-Reply-To: <my-message-id@example.com>" msgtxt1
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success $PREREQ,AUTOIDENT 'implicit ident is allowed' '
|
test_expect_success $PREREQ,AUTOIDENT 'implicit ident is allowed' '
|
||||||
|
Loading…
Reference in New Issue
Block a user