mirror of
https://github.com/git/git
synced 2024-11-04 16:17:49 +00:00
Merge branch 'ps/undecided-is-not-necessarily-sha1'
Before discovering the repository details, We used to assume SHA-1 as the "default" hash function, which has been corrected. Hopefully this will smoke out codepaths that rely on such an unwarranted assumptions. * ps/undecided-is-not-necessarily-sha1: repository: stop setting SHA1 as the default object hash oss-fuzz/commit-graph: set up hash algorithm builtin/shortlog: don't set up revisions without repo builtin/diff: explicitly set hash algo when there is no repo builtin/bundle: abort "verify" early when there is no repository builtin/blame: don't access potentially unitialized `the_hash_algo` builtin/rev-parse: allow shortening to more than 40 hex characters remote-curl: fix parsing of detached SHA256 heads attr: fix BUG() when parsing attrs outside of repo attr: don't recompute default attribute source parse-options-cb: only abbreviate hashes when hash algo is known path: move `validate_headref()` to its only user path: harden validation of HEAD with non-standard hashes
This commit is contained in:
commit
a60c21b720
17 changed files with 168 additions and 92 deletions
31
attr.c
31
attr.c
|
@ -1205,15 +1205,16 @@ static void collect_some_attrs(struct index_state *istate,
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *default_attr_source_tree_object_name;
|
static const char *default_attr_source_tree_object_name;
|
||||||
static int ignore_bad_attr_tree;
|
|
||||||
|
|
||||||
void set_git_attr_source(const char *tree_object_name)
|
void set_git_attr_source(const char *tree_object_name)
|
||||||
{
|
{
|
||||||
default_attr_source_tree_object_name = xstrdup(tree_object_name);
|
default_attr_source_tree_object_name = xstrdup(tree_object_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void compute_default_attr_source(struct object_id *attr_source)
|
static int compute_default_attr_source(struct object_id *attr_source)
|
||||||
{
|
{
|
||||||
|
int ignore_bad_attr_tree = 0;
|
||||||
|
|
||||||
if (!default_attr_source_tree_object_name)
|
if (!default_attr_source_tree_object_name)
|
||||||
default_attr_source_tree_object_name = getenv(GIT_ATTR_SOURCE_ENVIRONMENT);
|
default_attr_source_tree_object_name = getenv(GIT_ATTR_SOURCE_ENVIRONMENT);
|
||||||
|
|
||||||
|
@ -1222,22 +1223,34 @@ static void compute_default_attr_source(struct object_id *attr_source)
|
||||||
ignore_bad_attr_tree = 1;
|
ignore_bad_attr_tree = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!default_attr_source_tree_object_name || !is_null_oid(attr_source))
|
if (!default_attr_source_tree_object_name)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
|
if (!startup_info->have_repository) {
|
||||||
|
if (!ignore_bad_attr_tree)
|
||||||
|
die(_("cannot use --attr-source or GIT_ATTR_SOURCE without repo"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (repo_get_oid_treeish(the_repository,
|
if (repo_get_oid_treeish(the_repository,
|
||||||
default_attr_source_tree_object_name,
|
default_attr_source_tree_object_name,
|
||||||
attr_source) && !ignore_bad_attr_tree)
|
attr_source)) {
|
||||||
die(_("bad --attr-source or GIT_ATTR_SOURCE"));
|
if (!ignore_bad_attr_tree)
|
||||||
|
die(_("bad --attr-source or GIT_ATTR_SOURCE"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct object_id *default_attr_source(void)
|
static struct object_id *default_attr_source(void)
|
||||||
{
|
{
|
||||||
static struct object_id attr_source;
|
static struct object_id attr_source;
|
||||||
|
static int has_attr_source = -1;
|
||||||
|
|
||||||
if (is_null_oid(&attr_source))
|
if (has_attr_source < 0)
|
||||||
compute_default_attr_source(&attr_source);
|
has_attr_source = compute_default_attr_source(&attr_source);
|
||||||
if (is_null_oid(&attr_source))
|
if (!has_attr_source)
|
||||||
return NULL;
|
return NULL;
|
||||||
return &attr_source;
|
return &attr_source;
|
||||||
}
|
}
|
||||||
|
|
|
@ -915,7 +915,6 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
struct range_set ranges;
|
struct range_set ranges;
|
||||||
unsigned int range_i;
|
unsigned int range_i;
|
||||||
long anchor;
|
long anchor;
|
||||||
const int hexsz = the_hash_algo->hexsz;
|
|
||||||
long num_lines = 0;
|
long num_lines = 0;
|
||||||
const char *str_usage = cmd_is_annotate ? annotate_usage : blame_usage;
|
const char *str_usage = cmd_is_annotate ? annotate_usage : blame_usage;
|
||||||
const char **opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage;
|
const char **opt_usage = cmd_is_annotate ? annotate_opt_usage : blame_opt_usage;
|
||||||
|
@ -973,11 +972,11 @@ int cmd_blame(int argc, const char **argv, const char *prefix)
|
||||||
} else if (show_progress < 0)
|
} else if (show_progress < 0)
|
||||||
show_progress = isatty(2);
|
show_progress = isatty(2);
|
||||||
|
|
||||||
if (0 < abbrev && abbrev < hexsz)
|
if (0 < abbrev && abbrev < (int)the_hash_algo->hexsz)
|
||||||
/* one more abbrev length is needed for the boundary commit */
|
/* one more abbrev length is needed for the boundary commit */
|
||||||
abbrev++;
|
abbrev++;
|
||||||
else if (!abbrev)
|
else if (!abbrev)
|
||||||
abbrev = hexsz;
|
abbrev = the_hash_algo->hexsz;
|
||||||
|
|
||||||
if (revs_file && read_ancestry(revs_file))
|
if (revs_file && read_ancestry(revs_file))
|
||||||
die_errno("reading graft file '%s' failed", revs_file);
|
die_errno("reading graft file '%s' failed", revs_file);
|
||||||
|
|
|
@ -140,6 +140,11 @@ static int cmd_bundle_verify(int argc, const char **argv, const char *prefix) {
|
||||||
builtin_bundle_verify_usage, options, &bundle_file);
|
builtin_bundle_verify_usage, options, &bundle_file);
|
||||||
/* bundle internals use argv[1] as further parameters */
|
/* bundle internals use argv[1] as further parameters */
|
||||||
|
|
||||||
|
if (!startup_info->have_repository) {
|
||||||
|
ret = error(_("need a repository to verify a bundle"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
if ((bundle_fd = open_bundle(bundle_file, &header, &name)) < 0) {
|
if ((bundle_fd = open_bundle(bundle_file, &header, &name)) < 0) {
|
||||||
ret = 1;
|
ret = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
|
@ -465,6 +465,15 @@ int cmd_diff(int argc, const char **argv, const char *prefix)
|
||||||
no_index = DIFF_NO_INDEX_IMPLICIT;
|
no_index = DIFF_NO_INDEX_IMPLICIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When operating outside of a Git repository we need to have a hash
|
||||||
|
* algorithm at hand so that we can generate the blob hashes. We
|
||||||
|
* default to SHA1 here, but may eventually want to change this to be
|
||||||
|
* configurable via a command line option.
|
||||||
|
*/
|
||||||
|
if (nongit)
|
||||||
|
repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
|
||||||
|
|
||||||
init_diff_ui_defaults();
|
init_diff_ui_defaults();
|
||||||
git_config(git_diff_ui_config, NULL);
|
git_config(git_diff_ui_config, NULL);
|
||||||
prefix = precompose_argv_prefix(argc, argv, prefix);
|
prefix = precompose_argv_prefix(argc, argv, prefix);
|
||||||
|
|
|
@ -691,7 +691,6 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
||||||
const char *name = NULL;
|
const char *name = NULL;
|
||||||
struct object_context unused;
|
struct object_context unused;
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
const int hexsz = the_hash_algo->hexsz;
|
|
||||||
int seen_end_of_options = 0;
|
int seen_end_of_options = 0;
|
||||||
enum format_type format = FORMAT_DEFAULT;
|
enum format_type format = FORMAT_DEFAULT;
|
||||||
|
|
||||||
|
@ -867,8 +866,8 @@ int cmd_rev_parse(int argc, const char **argv, const char *prefix)
|
||||||
abbrev = strtoul(arg, NULL, 10);
|
abbrev = strtoul(arg, NULL, 10);
|
||||||
if (abbrev < MINIMUM_ABBREV)
|
if (abbrev < MINIMUM_ABBREV)
|
||||||
abbrev = MINIMUM_ABBREV;
|
abbrev = MINIMUM_ABBREV;
|
||||||
else if (hexsz <= abbrev)
|
else if ((int)the_hash_algo->hexsz <= abbrev)
|
||||||
abbrev = hexsz;
|
abbrev = the_hash_algo->hexsz;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!strcmp(arg, "--sq")) {
|
if (!strcmp(arg, "--sq")) {
|
||||||
|
|
|
@ -435,7 +435,7 @@ int cmd_shortlog(int argc, const char **argv, const char *prefix)
|
||||||
usage_with_options(shortlog_usage, options);
|
usage_with_options(shortlog_usage, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setup_revisions(argc, argv, &rev, NULL) != 1) {
|
if (!nongit && setup_revisions(argc, argv, &rev, NULL) != 1) {
|
||||||
error(_("unrecognized argument: %s"), argv[1]);
|
error(_("unrecognized argument: %s"), argv[1]);
|
||||||
usage_with_options(shortlog_usage, options);
|
usage_with_options(shortlog_usage, options);
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
|
||||||
* touching the disk to keep the individual fuzz-test cases as fast as
|
* touching the disk to keep the individual fuzz-test cases as fast as
|
||||||
* possible.
|
* possible.
|
||||||
*/
|
*/
|
||||||
|
repo_set_hash_algo(the_repository, GIT_HASH_SHA1);
|
||||||
the_repository->settings.commit_graph_generation_version = 2;
|
the_repository->settings.commit_graph_generation_version = 2;
|
||||||
the_repository->settings.commit_graph_read_changed_paths = 1;
|
the_repository->settings.commit_graph_read_changed_paths = 1;
|
||||||
g = parse_commit_graph(&the_repository->settings, (void *)data, size);
|
g = parse_commit_graph(&the_repository->settings, (void *)data, size);
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "object-name.h"
|
#include "object-name.h"
|
||||||
|
#include "setup.h"
|
||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
#include "strvec.h"
|
#include "strvec.h"
|
||||||
#include "oid-array.h"
|
#include "oid-array.h"
|
||||||
|
@ -29,7 +30,7 @@ int parse_opt_abbrev_cb(const struct option *opt, const char *arg, int unset)
|
||||||
opt->long_name);
|
opt->long_name);
|
||||||
if (v && v < MINIMUM_ABBREV)
|
if (v && v < MINIMUM_ABBREV)
|
||||||
v = MINIMUM_ABBREV;
|
v = MINIMUM_ABBREV;
|
||||||
else if (v > the_hash_algo->hexsz)
|
else if (startup_info->have_repository && v > the_hash_algo->hexsz)
|
||||||
v = the_hash_algo->hexsz;
|
v = the_hash_algo->hexsz;
|
||||||
}
|
}
|
||||||
*(int *)(opt->value) = v;
|
*(int *)(opt->value) = v;
|
||||||
|
|
53
path.c
53
path.c
|
@ -5,7 +5,6 @@
|
||||||
#include "abspath.h"
|
#include "abspath.h"
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
#include "hex.h"
|
|
||||||
#include "repository.h"
|
#include "repository.h"
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "string-list.h"
|
#include "string-list.h"
|
||||||
|
@ -647,58 +646,6 @@ void strbuf_git_common_path(struct strbuf *sb,
|
||||||
va_end(args);
|
va_end(args);
|
||||||
}
|
}
|
||||||
|
|
||||||
int validate_headref(const char *path)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
char buffer[256];
|
|
||||||
const char *refname;
|
|
||||||
struct object_id oid;
|
|
||||||
int fd;
|
|
||||||
ssize_t len;
|
|
||||||
|
|
||||||
if (lstat(path, &st) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* Make sure it is a "refs/.." symlink */
|
|
||||||
if (S_ISLNK(st.st_mode)) {
|
|
||||||
len = readlink(path, buffer, sizeof(buffer)-1);
|
|
||||||
if (len >= 5 && !memcmp("refs/", buffer, 5))
|
|
||||||
return 0;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Anything else, just open it and try to see if it is a symbolic ref.
|
|
||||||
*/
|
|
||||||
fd = open(path, O_RDONLY);
|
|
||||||
if (fd < 0)
|
|
||||||
return -1;
|
|
||||||
len = read_in_full(fd, buffer, sizeof(buffer)-1);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
if (len < 0)
|
|
||||||
return -1;
|
|
||||||
buffer[len] = '\0';
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Is it a symbolic ref?
|
|
||||||
*/
|
|
||||||
if (skip_prefix(buffer, "ref:", &refname)) {
|
|
||||||
while (isspace(*refname))
|
|
||||||
refname++;
|
|
||||||
if (starts_with(refname, "refs/"))
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Is this a detached HEAD?
|
|
||||||
*/
|
|
||||||
if (!get_oid_hex(buffer, &oid))
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct passwd *getpw_str(const char *username, size_t len)
|
static struct passwd *getpw_str(const char *username, size_t len)
|
||||||
{
|
{
|
||||||
struct passwd *pw;
|
struct passwd *pw;
|
||||||
|
|
1
path.h
1
path.h
|
@ -173,7 +173,6 @@ const char *git_path_fetch_head(struct repository *r);
|
||||||
const char *git_path_shallow(struct repository *r);
|
const char *git_path_shallow(struct repository *r);
|
||||||
|
|
||||||
int ends_with_path_components(const char *path, const char *components);
|
int ends_with_path_components(const char *path, const char *components);
|
||||||
int validate_headref(const char *ref);
|
|
||||||
|
|
||||||
int calc_shared_perm(int mode);
|
int calc_shared_perm(int mode);
|
||||||
int adjust_shared_perm(const char *path);
|
int adjust_shared_perm(const char *path);
|
||||||
|
|
|
@ -266,12 +266,23 @@ static struct ref *parse_git_refs(struct discovery *heads, int for_push)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Try to detect the hash algorithm used by the remote repository when using
|
||||||
|
* the dumb HTTP transport. As dumb transports cannot tell us the object hash
|
||||||
|
* directly have to derive it from the advertised ref lengths.
|
||||||
|
*/
|
||||||
static const struct git_hash_algo *detect_hash_algo(struct discovery *heads)
|
static const struct git_hash_algo *detect_hash_algo(struct discovery *heads)
|
||||||
{
|
{
|
||||||
const char *p = memchr(heads->buf, '\t', heads->len);
|
const char *p = memchr(heads->buf, '\t', heads->len);
|
||||||
int algo;
|
int algo;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In case the remote has no refs we have no way to reliably determine
|
||||||
|
* the object hash used by that repository. In that case we simply fall
|
||||||
|
* back to SHA1, which may or may not be correct.
|
||||||
|
*/
|
||||||
if (!p)
|
if (!p)
|
||||||
return the_hash_algo;
|
return &hash_algos[GIT_HASH_SHA1];
|
||||||
|
|
||||||
algo = hash_algo_by_length((p - heads->buf) / 2);
|
algo = hash_algo_by_length((p - heads->buf) / 2);
|
||||||
if (algo == GIT_HASH_UNKNOWN)
|
if (algo == GIT_HASH_UNKNOWN)
|
||||||
|
@ -295,6 +306,12 @@ static struct ref *parse_info_refs(struct discovery *heads)
|
||||||
"is this a git repository?",
|
"is this a git repository?",
|
||||||
transport_anonymize_url(url.buf));
|
transport_anonymize_url(url.buf));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Set the repository's hash algo to whatever we have just detected.
|
||||||
|
* This ensures that we can correctly parse the remote references.
|
||||||
|
*/
|
||||||
|
repo_set_hash_algo(the_repository, hash_algo_by_ptr(options.hash_algo));
|
||||||
|
|
||||||
data = heads->buf;
|
data = heads->buf;
|
||||||
start = NULL;
|
start = NULL;
|
||||||
mid = data;
|
mid = data;
|
||||||
|
|
20
repository.c
20
repository.c
|
@ -26,26 +26,6 @@ void initialize_repository(struct repository *repo)
|
||||||
repo->parsed_objects = parsed_object_pool_new();
|
repo->parsed_objects = parsed_object_pool_new();
|
||||||
ALLOC_ARRAY(repo->index, 1);
|
ALLOC_ARRAY(repo->index, 1);
|
||||||
index_state_init(repo->index, repo);
|
index_state_init(repo->index, repo);
|
||||||
|
|
||||||
/*
|
|
||||||
* Unfortunately, we need to keep this hack around for the time being:
|
|
||||||
*
|
|
||||||
* - Not setting up the hash algorithm for `the_repository` leads to
|
|
||||||
* crashes because `the_hash_algo` is a macro that expands to
|
|
||||||
* `the_repository->hash_algo`. So if Git commands try to access
|
|
||||||
* `the_hash_algo` without a Git directory we crash.
|
|
||||||
*
|
|
||||||
* - Setting up the hash algorithm to be SHA1 by default breaks other
|
|
||||||
* commands when running with SHA256.
|
|
||||||
*
|
|
||||||
* This is another point in case why having global state is a bad idea.
|
|
||||||
* Eventually, we should remove this hack and stop setting the hash
|
|
||||||
* algorithm in this function altogether. Instead, it should only ever
|
|
||||||
* be set via our repository setup procedures. But that requires more
|
|
||||||
* work.
|
|
||||||
*/
|
|
||||||
if (repo == the_repository)
|
|
||||||
repo_set_hash_algo(repo, GIT_HASH_SHA1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void expand_base_dir(char **out, const char *in,
|
static void expand_base_dir(char **out, const char *in,
|
||||||
|
|
53
setup.c
53
setup.c
|
@ -4,6 +4,7 @@
|
||||||
#include "environment.h"
|
#include "environment.h"
|
||||||
#include "exec-cmd.h"
|
#include "exec-cmd.h"
|
||||||
#include "gettext.h"
|
#include "gettext.h"
|
||||||
|
#include "hex.h"
|
||||||
#include "object-name.h"
|
#include "object-name.h"
|
||||||
#include "refs.h"
|
#include "refs.h"
|
||||||
#include "repository.h"
|
#include "repository.h"
|
||||||
|
@ -342,6 +343,58 @@ int get_common_dir_noenv(struct strbuf *sb, const char *gitdir)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int validate_headref(const char *path)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
char buffer[256];
|
||||||
|
const char *refname;
|
||||||
|
struct object_id oid;
|
||||||
|
int fd;
|
||||||
|
ssize_t len;
|
||||||
|
|
||||||
|
if (lstat(path, &st) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* Make sure it is a "refs/.." symlink */
|
||||||
|
if (S_ISLNK(st.st_mode)) {
|
||||||
|
len = readlink(path, buffer, sizeof(buffer)-1);
|
||||||
|
if (len >= 5 && !memcmp("refs/", buffer, 5))
|
||||||
|
return 0;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Anything else, just open it and try to see if it is a symbolic ref.
|
||||||
|
*/
|
||||||
|
fd = open(path, O_RDONLY);
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
len = read_in_full(fd, buffer, sizeof(buffer)-1);
|
||||||
|
close(fd);
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
return -1;
|
||||||
|
buffer[len] = '\0';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is it a symbolic ref?
|
||||||
|
*/
|
||||||
|
if (skip_prefix(buffer, "ref:", &refname)) {
|
||||||
|
while (isspace(*refname))
|
||||||
|
refname++;
|
||||||
|
if (starts_with(refname, "refs/"))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Is this a detached HEAD?
|
||||||
|
*/
|
||||||
|
if (get_oid_hex_any(buffer, &oid) != GIT_HASH_UNKNOWN)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test if it looks like we're at a git directory.
|
* Test if it looks like we're at a git directory.
|
||||||
* We want to see:
|
* We want to see:
|
||||||
|
|
|
@ -434,6 +434,21 @@ test_expect_success 'precedence of --attr-source, GIT_ATTR_SOURCE, then attr.tre
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'diff without repository with attr source' '
|
||||||
|
mkdir -p "$TRASH_DIRECTORY/outside/nongit" &&
|
||||||
|
(
|
||||||
|
cd "$TRASH_DIRECTORY/outside/nongit" &&
|
||||||
|
GIT_CEILING_DIRECTORIES="$TRASH_DIRECTORY/outside" &&
|
||||||
|
export GIT_CEILING_DIRECTORIES &&
|
||||||
|
touch file &&
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
fatal: cannot use --attr-source or GIT_ATTR_SOURCE without repo
|
||||||
|
EOF
|
||||||
|
test_must_fail env GIT_ATTR_SOURCE=HEAD git grep --no-index foo file 2>err &&
|
||||||
|
test_cmp expect err
|
||||||
|
)
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'bare repository: with --source' '
|
test_expect_success 'bare repository: with --source' '
|
||||||
(
|
(
|
||||||
cd bare.git &&
|
cd bare.git &&
|
||||||
|
|
|
@ -176,6 +176,23 @@ test_expect_success 'long options' '
|
||||||
test_cmp expect output
|
test_cmp expect output
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success 'abbreviate to something longer than SHA1 length' '
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
boolean: 0
|
||||||
|
integer: 0
|
||||||
|
magnitude: 0
|
||||||
|
timestamp: 0
|
||||||
|
string: (not set)
|
||||||
|
abbrev: 100
|
||||||
|
verbose: -1
|
||||||
|
quiet: 0
|
||||||
|
dry run: no
|
||||||
|
file: (not set)
|
||||||
|
EOF
|
||||||
|
test-tool parse-options --abbrev=100 >output &&
|
||||||
|
test_cmp expect output
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'missing required value' '
|
test_expect_success 'missing required value' '
|
||||||
cat >expect <<-\EOF &&
|
cat >expect <<-\EOF &&
|
||||||
error: switch `s'\'' requires a value
|
error: switch `s'\'' requires a value
|
||||||
|
|
|
@ -304,4 +304,10 @@ test_expect_success 'rev-parse --bisect includes bad, excludes good' '
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
test_expect_success '--short= truncates to the actual hash length' '
|
||||||
|
git rev-parse HEAD >expect &&
|
||||||
|
git rev-parse --short=100 HEAD >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
|
|
@ -55,6 +55,21 @@ test_expect_success 'list refs from outside any repository' '
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
|
|
||||||
|
test_expect_success 'list detached HEAD from outside any repository' '
|
||||||
|
git clone --mirror "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
|
||||||
|
"$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" &&
|
||||||
|
git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" \
|
||||||
|
update-ref --no-deref HEAD refs/heads/main &&
|
||||||
|
git -C "$HTTPD_DOCUMENT_ROOT_PATH/repo-detached.git" update-server-info &&
|
||||||
|
cat >expect <<-EOF &&
|
||||||
|
$(git rev-parse main) HEAD
|
||||||
|
$(git rev-parse main) refs/heads/main
|
||||||
|
EOF
|
||||||
|
nongit git ls-remote "$HTTPD_URL/dumb/repo-detached.git" >actual &&
|
||||||
|
test_cmp expect actual
|
||||||
|
'
|
||||||
|
|
||||||
test_expect_success 'create password-protected repository' '
|
test_expect_success 'create password-protected repository' '
|
||||||
mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&
|
mkdir -p "$HTTPD_DOCUMENT_ROOT_PATH/auth/dumb/" &&
|
||||||
cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
|
cp -Rf "$HTTPD_DOCUMENT_ROOT_PATH/repo.git" \
|
||||||
|
|
Loading…
Reference in a new issue