Merge branch 'jk/no-funny-object-types'
Support to create a loose object file with unknown object type has been dropped. * jk/no-funny-object-types: object-file: drop support for writing objects with unknown types hash-object: handle --literally with OPT_NEGBIT hash-object: merge HASH_* and INDEX_* flags hash-object: stop allowing unknown types t: add lib-loose.sh t/helper: add zlib test-tool oid_object_info(): drop type_name strbuf fsck: stop using object_info->type_name strbuf oid_object_info_convert(): stop using string for object type cat-file: use type enum instead of buffer for -t option object-file: drop OBJECT_INFO_ALLOW_UNKNOWN_TYPE flag cat-file: make --allow-unknown-type a noop object-file.h: fix typo in variable declarationmaint
commit
17d9dbd3c2
|
@ -9,8 +9,7 @@ SYNOPSIS
|
||||||
--------
|
--------
|
||||||
[verse]
|
[verse]
|
||||||
'git cat-file' <type> <object>
|
'git cat-file' <type> <object>
|
||||||
'git cat-file' (-e | -p) <object>
|
'git cat-file' (-e | -p | -t | -s) <object>
|
||||||
'git cat-file' (-t | -s) [--allow-unknown-type] <object>
|
|
||||||
'git cat-file' (--textconv | --filters)
|
'git cat-file' (--textconv | --filters)
|
||||||
[<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]
|
[<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]
|
||||||
'git cat-file' (--batch | --batch-check | --batch-command) [--batch-all-objects]
|
'git cat-file' (--batch | --batch-check | --batch-command) [--batch-all-objects]
|
||||||
|
@ -202,9 +201,6 @@ flush::
|
||||||
only once, even if it is stored multiple times in the
|
only once, even if it is stored multiple times in the
|
||||||
repository.
|
repository.
|
||||||
|
|
||||||
--allow-unknown-type::
|
|
||||||
Allow `-s` or `-t` to query broken/corrupt objects of unknown type.
|
|
||||||
|
|
||||||
--follow-symlinks::
|
--follow-symlinks::
|
||||||
With `--batch` or `--batch-check`, follow symlinks inside the
|
With `--batch` or `--batch-check`, follow symlinks inside the
|
||||||
repository when requesting objects with extended SHA-1
|
repository when requesting objects with extended SHA-1
|
||||||
|
|
1
Makefile
1
Makefile
|
@ -859,6 +859,7 @@ TEST_BUILTINS_OBJS += test-wildmatch.o
|
||||||
TEST_BUILTINS_OBJS += test-windows-named-pipe.o
|
TEST_BUILTINS_OBJS += test-windows-named-pipe.o
|
||||||
TEST_BUILTINS_OBJS += test-write-cache.o
|
TEST_BUILTINS_OBJS += test-write-cache.o
|
||||||
TEST_BUILTINS_OBJS += test-xml-encode.o
|
TEST_BUILTINS_OBJS += test-xml-encode.o
|
||||||
|
TEST_BUILTINS_OBJS += test-zlib.o
|
||||||
|
|
||||||
# Do not add more tests here unless they have extra dependencies. Add
|
# Do not add more tests here unless they have extra dependencies. Add
|
||||||
# them in TEST_BUILTINS_OBJS above.
|
# them in TEST_BUILTINS_OBJS above.
|
||||||
|
|
|
@ -100,8 +100,7 @@ static int stream_blob(const struct object_id *oid)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
|
||||||
int unknown_type)
|
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
|
@ -110,7 +109,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
struct object_context obj_context = {0};
|
struct object_context obj_context = {0};
|
||||||
struct object_info oi = OBJECT_INFO_INIT;
|
struct object_info oi = OBJECT_INFO_INIT;
|
||||||
struct strbuf sb = STRBUF_INIT;
|
|
||||||
unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
|
unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
|
||||||
unsigned get_oid_flags =
|
unsigned get_oid_flags =
|
||||||
GET_OID_RECORD_PATH |
|
GET_OID_RECORD_PATH |
|
||||||
|
@ -121,9 +119,6 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
||||||
if (!path && opt_cw)
|
if (!path && opt_cw)
|
||||||
get_oid_flags |= GET_OID_REQUIRE_PATH;
|
get_oid_flags |= GET_OID_REQUIRE_PATH;
|
||||||
|
|
||||||
if (unknown_type)
|
|
||||||
flags |= OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
|
|
||||||
|
|
||||||
if (get_oid_with_context(the_repository, obj_name, get_oid_flags, &oid,
|
if (get_oid_with_context(the_repository, obj_name, get_oid_flags, &oid,
|
||||||
&obj_context))
|
&obj_context))
|
||||||
die("Not a valid object name %s", obj_name);
|
die("Not a valid object name %s", obj_name);
|
||||||
|
@ -136,16 +131,12 @@ static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 't':
|
case 't':
|
||||||
oi.type_name = &sb;
|
oi.typep = &type;
|
||||||
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
|
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
|
||||||
die("git cat-file: could not get object info");
|
die("git cat-file: could not get object info");
|
||||||
if (sb.len) {
|
printf("%s\n", type_name(type));
|
||||||
printf("%s\n", sb.buf);
|
|
||||||
strbuf_release(&sb);
|
|
||||||
ret = 0;
|
ret = 0;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 's':
|
case 's':
|
||||||
oi.sizep = &size;
|
oi.sizep = &size;
|
||||||
|
@ -1038,8 +1029,7 @@ int cmd_cat_file(int argc,
|
||||||
|
|
||||||
const char * const builtin_catfile_usage[] = {
|
const char * const builtin_catfile_usage[] = {
|
||||||
N_("git cat-file <type> <object>"),
|
N_("git cat-file <type> <object>"),
|
||||||
N_("git cat-file (-e | -p) <object>"),
|
N_("git cat-file (-e | -p | -t | -s) <object>"),
|
||||||
N_("git cat-file (-t | -s) [--allow-unknown-type] <object>"),
|
|
||||||
N_("git cat-file (--textconv | --filters)\n"
|
N_("git cat-file (--textconv | --filters)\n"
|
||||||
" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"),
|
" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"),
|
||||||
N_("git cat-file (--batch | --batch-check | --batch-command) [--batch-all-objects]\n"
|
N_("git cat-file (--batch | --batch-check | --batch-command) [--batch-all-objects]\n"
|
||||||
|
@ -1057,8 +1047,8 @@ int cmd_cat_file(int argc,
|
||||||
OPT_GROUP(N_("Emit [broken] object attributes")),
|
OPT_GROUP(N_("Emit [broken] object attributes")),
|
||||||
OPT_CMDMODE('t', NULL, &opt, N_("show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"), 't'),
|
OPT_CMDMODE('t', NULL, &opt, N_("show object type (one of 'blob', 'tree', 'commit', 'tag', ...)"), 't'),
|
||||||
OPT_CMDMODE('s', NULL, &opt, N_("show object size"), 's'),
|
OPT_CMDMODE('s', NULL, &opt, N_("show object size"), 's'),
|
||||||
OPT_BOOL(0, "allow-unknown-type", &unknown_type,
|
OPT_HIDDEN_BOOL(0, "allow-unknown-type", &unknown_type,
|
||||||
N_("allow -s and -t to work with broken/corrupt objects")),
|
N_("historical option -- no-op")),
|
||||||
OPT_BOOL(0, "use-mailmap", &use_mailmap, N_("use mail map file")),
|
OPT_BOOL(0, "use-mailmap", &use_mailmap, N_("use mail map file")),
|
||||||
OPT_ALIAS(0, "mailmap", "use-mailmap"),
|
OPT_ALIAS(0, "mailmap", "use-mailmap"),
|
||||||
/* Batch mode */
|
/* Batch mode */
|
||||||
|
@ -1209,10 +1199,7 @@ int cmd_cat_file(int argc,
|
||||||
obj_name = argv[1];
|
obj_name = argv[1];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unknown_type && opt != 't' && opt != 's')
|
ret = cat_one_file(opt, exp_type, obj_name);
|
||||||
die("git cat-file --allow-unknown-type: use with -s or -t");
|
|
||||||
|
|
||||||
ret = cat_one_file(opt, exp_type, obj_name, unknown_type);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
list_objects_filter_release(&batch.objects_filter);
|
list_objects_filter_release(&batch.objects_filter);
|
||||||
|
|
|
@ -614,12 +614,11 @@ static void get_default_heads(void)
|
||||||
struct for_each_loose_cb
|
struct for_each_loose_cb
|
||||||
{
|
{
|
||||||
struct progress *progress;
|
struct progress *progress;
|
||||||
struct strbuf obj_type;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int fsck_loose(const struct object_id *oid, const char *path, void *data)
|
static int fsck_loose(const struct object_id *oid, const char *path,
|
||||||
|
void *data UNUSED)
|
||||||
{
|
{
|
||||||
struct for_each_loose_cb *cb_data = data;
|
|
||||||
struct object *obj;
|
struct object *obj;
|
||||||
enum object_type type = OBJ_NONE;
|
enum object_type type = OBJ_NONE;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
@ -629,8 +628,6 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)
|
||||||
struct object_id real_oid = *null_oid(the_hash_algo);
|
struct object_id real_oid = *null_oid(the_hash_algo);
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
strbuf_reset(&cb_data->obj_type);
|
|
||||||
oi.type_name = &cb_data->obj_type;
|
|
||||||
oi.sizep = &size;
|
oi.sizep = &size;
|
||||||
oi.typep = &type;
|
oi.typep = &type;
|
||||||
|
|
||||||
|
@ -642,10 +639,6 @@ static int fsck_loose(const struct object_id *oid, const char *path, void *data)
|
||||||
err = error(_("%s: object corrupt or missing: %s"),
|
err = error(_("%s: object corrupt or missing: %s"),
|
||||||
oid_to_hex(oid), path);
|
oid_to_hex(oid), path);
|
||||||
}
|
}
|
||||||
if (type != OBJ_NONE && type < 0)
|
|
||||||
err = error(_("%s: object is of unknown type '%s': %s"),
|
|
||||||
oid_to_hex(&real_oid), cb_data->obj_type.buf,
|
|
||||||
path);
|
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
errors_found |= ERROR_OBJECT;
|
errors_found |= ERROR_OBJECT;
|
||||||
free(contents);
|
free(contents);
|
||||||
|
@ -697,7 +690,6 @@ static void fsck_object_dir(const char *path)
|
||||||
{
|
{
|
||||||
struct progress *progress = NULL;
|
struct progress *progress = NULL;
|
||||||
struct for_each_loose_cb cb_data = {
|
struct for_each_loose_cb cb_data = {
|
||||||
.obj_type = STRBUF_INIT,
|
|
||||||
.progress = progress,
|
.progress = progress,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -712,7 +704,6 @@ static void fsck_object_dir(const char *path)
|
||||||
&cb_data);
|
&cb_data);
|
||||||
display_progress(progress, 256);
|
display_progress(progress, 256);
|
||||||
stop_progress(&progress);
|
stop_progress(&progress);
|
||||||
strbuf_release(&cb_data.obj_type);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int fsck_head_link(const char *head_ref_name,
|
static int fsck_head_link(const char *head_ref_name,
|
||||||
|
|
|
@ -19,49 +19,15 @@
|
||||||
#include "strbuf.h"
|
#include "strbuf.h"
|
||||||
#include "write-or-die.h"
|
#include "write-or-die.h"
|
||||||
|
|
||||||
enum {
|
static void hash_fd(int fd, const char *type, const char *path, unsigned flags)
|
||||||
HASH_OBJECT_CHECK = (1 << 0),
|
|
||||||
HASH_OBJECT_WRITE = (1 << 1),
|
|
||||||
};
|
|
||||||
|
|
||||||
/*
|
|
||||||
* This is to create corrupt objects for debugging and as such it
|
|
||||||
* needs to bypass the data conversion performed by, and the type
|
|
||||||
* limitation imposed by, index_fd() and its callees.
|
|
||||||
*/
|
|
||||||
static int hash_literally(struct object_id *oid, int fd, const char *type, unsigned flags)
|
|
||||||
{
|
{
|
||||||
struct strbuf buf = STRBUF_INIT;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
if (strbuf_read(&buf, fd, 4096) < 0)
|
|
||||||
ret = -1;
|
|
||||||
else
|
|
||||||
ret = write_object_file_literally(buf.buf, buf.len, type, oid,
|
|
||||||
(flags & HASH_OBJECT_WRITE) ? WRITE_OBJECT_FILE_PERSIST : 0);
|
|
||||||
close(fd);
|
|
||||||
strbuf_release(&buf);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void hash_fd(int fd, const char *type, const char *path, unsigned flags,
|
|
||||||
int literally)
|
|
||||||
{
|
|
||||||
unsigned int index_flags = 0;
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
struct object_id oid;
|
struct object_id oid;
|
||||||
|
|
||||||
if (flags & HASH_OBJECT_WRITE)
|
|
||||||
index_flags |= INDEX_WRITE_OBJECT;
|
|
||||||
if (flags & HASH_OBJECT_CHECK)
|
|
||||||
index_flags |= INDEX_FORMAT_CHECK;
|
|
||||||
|
|
||||||
if (fstat(fd, &st) < 0 ||
|
if (fstat(fd, &st) < 0 ||
|
||||||
(literally
|
index_fd(the_repository->index, &oid, fd, &st,
|
||||||
? hash_literally(&oid, fd, type, flags)
|
type_from_string(type), path, flags))
|
||||||
: index_fd(the_repository->index, &oid, fd, &st,
|
die((flags & INDEX_WRITE_OBJECT)
|
||||||
type_from_string(type), path, index_flags)))
|
|
||||||
die((flags & HASH_OBJECT_WRITE)
|
|
||||||
? "Unable to add %s to database"
|
? "Unable to add %s to database"
|
||||||
: "Unable to hash %s", path);
|
: "Unable to hash %s", path);
|
||||||
printf("%s\n", oid_to_hex(&oid));
|
printf("%s\n", oid_to_hex(&oid));
|
||||||
|
@ -69,15 +35,14 @@ static void hash_fd(int fd, const char *type, const char *path, unsigned flags,
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hash_object(const char *path, const char *type, const char *vpath,
|
static void hash_object(const char *path, const char *type, const char *vpath,
|
||||||
unsigned flags, int literally)
|
unsigned flags)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
fd = xopen(path, O_RDONLY);
|
fd = xopen(path, O_RDONLY);
|
||||||
hash_fd(fd, type, vpath, flags, literally);
|
hash_fd(fd, type, vpath, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
|
static void hash_stdin_paths(const char *type, int no_filters, unsigned flags)
|
||||||
int literally)
|
|
||||||
{
|
{
|
||||||
struct strbuf buf = STRBUF_INIT;
|
struct strbuf buf = STRBUF_INIT;
|
||||||
struct strbuf unquoted = STRBUF_INIT;
|
struct strbuf unquoted = STRBUF_INIT;
|
||||||
|
@ -89,8 +54,7 @@ static void hash_stdin_paths(const char *type, int no_filters, unsigned flags,
|
||||||
die("line is badly quoted");
|
die("line is badly quoted");
|
||||||
strbuf_swap(&buf, &unquoted);
|
strbuf_swap(&buf, &unquoted);
|
||||||
}
|
}
|
||||||
hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags,
|
hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags);
|
||||||
literally);
|
|
||||||
}
|
}
|
||||||
strbuf_release(&buf);
|
strbuf_release(&buf);
|
||||||
strbuf_release(&unquoted);
|
strbuf_release(&unquoted);
|
||||||
|
@ -111,19 +75,20 @@ int cmd_hash_object(int argc,
|
||||||
int hashstdin = 0;
|
int hashstdin = 0;
|
||||||
int stdin_paths = 0;
|
int stdin_paths = 0;
|
||||||
int no_filters = 0;
|
int no_filters = 0;
|
||||||
int literally = 0;
|
|
||||||
int nongit = 0;
|
int nongit = 0;
|
||||||
unsigned flags = HASH_OBJECT_CHECK;
|
unsigned flags = INDEX_FORMAT_CHECK;
|
||||||
const char *vpath = NULL;
|
const char *vpath = NULL;
|
||||||
char *vpath_free = NULL;
|
char *vpath_free = NULL;
|
||||||
const struct option hash_object_options[] = {
|
const struct option hash_object_options[] = {
|
||||||
OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
|
OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
|
||||||
OPT_BIT('w', NULL, &flags, N_("write the object into the object database"),
|
OPT_BIT('w', NULL, &flags, N_("write the object into the object database"),
|
||||||
HASH_OBJECT_WRITE),
|
INDEX_WRITE_OBJECT),
|
||||||
OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
|
OPT_COUNTUP( 0 , "stdin", &hashstdin, N_("read the object from stdin")),
|
||||||
OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
|
OPT_BOOL( 0 , "stdin-paths", &stdin_paths, N_("read file names from stdin")),
|
||||||
OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
|
OPT_BOOL( 0 , "no-filters", &no_filters, N_("store file as is without filters")),
|
||||||
OPT_BOOL( 0, "literally", &literally, N_("just hash any random garbage to create corrupt objects for debugging Git")),
|
OPT_NEGBIT( 0, "literally", &flags,
|
||||||
|
N_("just hash any random garbage to create corrupt objects for debugging Git"),
|
||||||
|
INDEX_FORMAT_CHECK),
|
||||||
OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
|
OPT_STRING( 0 , "path", &vpath, N_("file"), N_("process file as it were from this path")),
|
||||||
OPT_END()
|
OPT_END()
|
||||||
};
|
};
|
||||||
|
@ -133,7 +98,7 @@ int cmd_hash_object(int argc,
|
||||||
argc = parse_options(argc, argv, prefix, hash_object_options,
|
argc = parse_options(argc, argv, prefix, hash_object_options,
|
||||||
hash_object_usage, 0);
|
hash_object_usage, 0);
|
||||||
|
|
||||||
if (flags & HASH_OBJECT_WRITE)
|
if (flags & INDEX_WRITE_OBJECT)
|
||||||
prefix = setup_git_directory();
|
prefix = setup_git_directory();
|
||||||
else
|
else
|
||||||
prefix = setup_git_directory_gently(&nongit);
|
prefix = setup_git_directory_gently(&nongit);
|
||||||
|
@ -169,7 +134,7 @@ int cmd_hash_object(int argc,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hashstdin)
|
if (hashstdin)
|
||||||
hash_fd(0, type, vpath, flags, literally);
|
hash_fd(0, type, vpath, flags);
|
||||||
|
|
||||||
for (i = 0 ; i < argc; i++) {
|
for (i = 0 ; i < argc; i++) {
|
||||||
const char *arg = argv[i];
|
const char *arg = argv[i];
|
||||||
|
@ -178,12 +143,12 @@ int cmd_hash_object(int argc,
|
||||||
if (prefix)
|
if (prefix)
|
||||||
arg = to_free = prefix_filename(prefix, arg);
|
arg = to_free = prefix_filename(prefix, arg);
|
||||||
hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
|
hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
|
||||||
flags, literally);
|
flags);
|
||||||
free(to_free);
|
free(to_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stdin_paths)
|
if (stdin_paths)
|
||||||
hash_stdin_paths(type, no_filters, flags, literally);
|
hash_stdin_paths(type, no_filters, flags);
|
||||||
|
|
||||||
free(vpath_free);
|
free(vpath_free);
|
||||||
|
|
||||||
|
|
138
object-file.c
138
object-file.c
|
@ -130,12 +130,6 @@ int has_loose_object(const struct object_id *oid)
|
||||||
return check_and_freshen(oid, 0);
|
return check_and_freshen(oid, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int format_object_header_literally(char *str, size_t size,
|
|
||||||
const char *type, size_t objsize)
|
|
||||||
{
|
|
||||||
return xsnprintf(str, size, "%s %"PRIuMAX, type, (uintmax_t)objsize) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int format_object_header(char *str, size_t size, enum object_type type,
|
int format_object_header(char *str, size_t size, enum object_type type,
|
||||||
size_t objsize)
|
size_t objsize)
|
||||||
{
|
{
|
||||||
|
@ -144,7 +138,7 @@ int format_object_header(char *str, size_t size, enum object_type type,
|
||||||
if (!name)
|
if (!name)
|
||||||
BUG("could not get a type name for 'enum object_type' value %d", type);
|
BUG("could not get a type name for 'enum object_type' value %d", type);
|
||||||
|
|
||||||
return format_object_header_literally(str, size, name, objsize);
|
return xsnprintf(str, size, "%s %"PRIuMAX, name, (uintmax_t)objsize) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int check_object_signature(struct repository *r, const struct object_id *oid,
|
int check_object_signature(struct repository *r, const struct object_id *oid,
|
||||||
|
@ -299,8 +293,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
|
||||||
unsigned char *map,
|
unsigned char *map,
|
||||||
unsigned long mapsize,
|
unsigned long mapsize,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
unsigned long bufsiz,
|
unsigned long bufsiz)
|
||||||
struct strbuf *header)
|
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
|
@ -325,32 +318,9 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
|
||||||
return ULHR_OK;
|
return ULHR_OK;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We have a header longer than MAX_HEADER_LEN. The "header"
|
* We have a header longer than MAX_HEADER_LEN.
|
||||||
* here is only non-NULL when we run "cat-file
|
|
||||||
* --allow-unknown-type".
|
|
||||||
*/
|
*/
|
||||||
if (!header)
|
|
||||||
return ULHR_TOO_LONG;
|
return ULHR_TOO_LONG;
|
||||||
|
|
||||||
/*
|
|
||||||
* buffer[0..bufsiz] was not large enough. Copy the partial
|
|
||||||
* result out to header, and then append the result of further
|
|
||||||
* reading the stream.
|
|
||||||
*/
|
|
||||||
strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer);
|
|
||||||
|
|
||||||
do {
|
|
||||||
stream->next_out = buffer;
|
|
||||||
stream->avail_out = bufsiz;
|
|
||||||
|
|
||||||
obj_read_unlock();
|
|
||||||
status = git_inflate(stream, 0);
|
|
||||||
obj_read_lock();
|
|
||||||
strbuf_add(header, buffer, stream->next_out - (unsigned char *)buffer);
|
|
||||||
if (memchr(buffer, '\0', stream->next_out - (unsigned char *)buffer))
|
|
||||||
return 0;
|
|
||||||
} while (status == Z_OK);
|
|
||||||
return ULHR_BAD;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *unpack_loose_rest(git_zstream *stream,
|
static void *unpack_loose_rest(git_zstream *stream,
|
||||||
|
@ -427,8 +397,6 @@ int parse_loose_header(const char *hdr, struct object_info *oi)
|
||||||
}
|
}
|
||||||
|
|
||||||
type = type_from_string_gently(type_buf, type_len, 1);
|
type = type_from_string_gently(type_buf, type_len, 1);
|
||||||
if (oi->type_name)
|
|
||||||
strbuf_add(oi->type_name, type_buf, type_len);
|
|
||||||
if (oi->typep)
|
if (oi->typep)
|
||||||
*oi->typep = type;
|
*oi->typep = type;
|
||||||
|
|
||||||
|
@ -476,10 +444,8 @@ int loose_object_info(struct repository *r,
|
||||||
void *map;
|
void *map;
|
||||||
git_zstream stream;
|
git_zstream stream;
|
||||||
char hdr[MAX_HEADER_LEN];
|
char hdr[MAX_HEADER_LEN];
|
||||||
struct strbuf hdrbuf = STRBUF_INIT;
|
|
||||||
unsigned long size_scratch;
|
unsigned long size_scratch;
|
||||||
enum object_type type_scratch;
|
enum object_type type_scratch;
|
||||||
int allow_unknown = flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
|
|
||||||
|
|
||||||
if (oi->delta_base_oid)
|
if (oi->delta_base_oid)
|
||||||
oidclr(oi->delta_base_oid, the_repository->hash_algo);
|
oidclr(oi->delta_base_oid, the_repository->hash_algo);
|
||||||
|
@ -492,7 +458,7 @@ int loose_object_info(struct repository *r,
|
||||||
* return value implicitly indicates whether the
|
* return value implicitly indicates whether the
|
||||||
* object even exists.
|
* object even exists.
|
||||||
*/
|
*/
|
||||||
if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
|
if (!oi->typep && !oi->sizep && !oi->contentp) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
|
if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
|
||||||
return quick_has_loose(r, oid) ? 0 : -1;
|
return quick_has_loose(r, oid) ? 0 : -1;
|
||||||
|
@ -521,18 +487,15 @@ int loose_object_info(struct repository *r,
|
||||||
if (oi->disk_sizep)
|
if (oi->disk_sizep)
|
||||||
*oi->disk_sizep = mapsize;
|
*oi->disk_sizep = mapsize;
|
||||||
|
|
||||||
switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
|
switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) {
|
||||||
allow_unknown ? &hdrbuf : NULL)) {
|
|
||||||
case ULHR_OK:
|
case ULHR_OK:
|
||||||
if (parse_loose_header(hdrbuf.len ? hdrbuf.buf : hdr, oi) < 0)
|
if (parse_loose_header(hdr, oi) < 0)
|
||||||
status = error(_("unable to parse %s header"), oid_to_hex(oid));
|
status = error(_("unable to parse %s header"), oid_to_hex(oid));
|
||||||
else if (!allow_unknown && *oi->typep < 0)
|
else if (*oi->typep < 0)
|
||||||
die(_("invalid object type"));
|
die(_("invalid object type"));
|
||||||
|
|
||||||
if (!oi->contentp)
|
if (!oi->contentp)
|
||||||
break;
|
break;
|
||||||
if (hdrbuf.len)
|
|
||||||
BUG("unpacking content with unknown types not yet supported");
|
|
||||||
*oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
|
*oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
|
||||||
if (*oi->contentp)
|
if (*oi->contentp)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
@ -558,7 +521,6 @@ cleanup:
|
||||||
munmap(map, mapsize);
|
munmap(map, mapsize);
|
||||||
if (oi->sizep == &size_scratch)
|
if (oi->sizep == &size_scratch)
|
||||||
oi->sizep = NULL;
|
oi->sizep = NULL;
|
||||||
strbuf_release(&hdrbuf);
|
|
||||||
if (oi->typep == &type_scratch)
|
if (oi->typep == &type_scratch)
|
||||||
oi->typep = NULL;
|
oi->typep = NULL;
|
||||||
oi->whence = OI_LOOSE;
|
oi->whence = OI_LOOSE;
|
||||||
|
@ -590,17 +552,6 @@ static void write_object_file_prepare(const struct git_hash_algo *algo,
|
||||||
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
|
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void write_object_file_prepare_literally(const struct git_hash_algo *algo,
|
|
||||||
const void *buf, unsigned long len,
|
|
||||||
const char *type, struct object_id *oid,
|
|
||||||
char *hdr, int *hdrlen)
|
|
||||||
{
|
|
||||||
struct git_hash_ctx c;
|
|
||||||
|
|
||||||
*hdrlen = format_object_header_literally(hdr, *hdrlen, type, len);
|
|
||||||
hash_object_body(algo, &c, buf, len, oid, hdr, hdrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define CHECK_COLLISION_DEST_VANISHED -2
|
#define CHECK_COLLISION_DEST_VANISHED -2
|
||||||
|
|
||||||
static int check_collision(const char *source, const char *dest)
|
static int check_collision(const char *source, const char *dest)
|
||||||
|
@ -730,21 +681,14 @@ out:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hash_object_file_literally(const struct git_hash_algo *algo,
|
|
||||||
const void *buf, unsigned long len,
|
|
||||||
const char *type, struct object_id *oid)
|
|
||||||
{
|
|
||||||
char hdr[MAX_HEADER_LEN];
|
|
||||||
int hdrlen = sizeof(hdr);
|
|
||||||
|
|
||||||
write_object_file_prepare_literally(algo, buf, len, type, oid, hdr, &hdrlen);
|
|
||||||
}
|
|
||||||
|
|
||||||
void hash_object_file(const struct git_hash_algo *algo, const void *buf,
|
void hash_object_file(const struct git_hash_algo *algo, const void *buf,
|
||||||
unsigned long len, enum object_type type,
|
unsigned long len, enum object_type type,
|
||||||
struct object_id *oid)
|
struct object_id *oid)
|
||||||
{
|
{
|
||||||
hash_object_file_literally(algo, buf, len, type_name(type), oid);
|
char hdr[MAX_HEADER_LEN];
|
||||||
|
int hdrlen = sizeof(hdr);
|
||||||
|
|
||||||
|
write_object_file_prepare(algo, buf, len, type, oid, hdr, &hdrlen);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finalize a file on disk, and close it. */
|
/* Finalize a file on disk, and close it. */
|
||||||
|
@ -1146,53 +1090,6 @@ int write_object_file_flags(const void *buf, unsigned long len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int write_object_file_literally(const void *buf, unsigned long len,
|
|
||||||
const char *type, struct object_id *oid,
|
|
||||||
unsigned flags)
|
|
||||||
{
|
|
||||||
char *header;
|
|
||||||
struct repository *repo = the_repository;
|
|
||||||
const struct git_hash_algo *algo = repo->hash_algo;
|
|
||||||
const struct git_hash_algo *compat = repo->compat_hash_algo;
|
|
||||||
struct object_id compat_oid;
|
|
||||||
int hdrlen, status = 0;
|
|
||||||
int compat_type = -1;
|
|
||||||
|
|
||||||
if (compat) {
|
|
||||||
compat_type = type_from_string_gently(type, -1, 1);
|
|
||||||
if (compat_type == OBJ_BLOB)
|
|
||||||
hash_object_file(compat, buf, len, compat_type,
|
|
||||||
&compat_oid);
|
|
||||||
else if (compat_type != -1) {
|
|
||||||
struct strbuf converted = STRBUF_INIT;
|
|
||||||
convert_object_file(the_repository,
|
|
||||||
&converted, algo, compat,
|
|
||||||
buf, len, compat_type, 0);
|
|
||||||
hash_object_file(compat, converted.buf, converted.len,
|
|
||||||
compat_type, &compat_oid);
|
|
||||||
strbuf_release(&converted);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* type string, SP, %lu of the length plus NUL must fit this */
|
|
||||||
hdrlen = strlen(type) + MAX_HEADER_LEN;
|
|
||||||
header = xmalloc(hdrlen);
|
|
||||||
write_object_file_prepare_literally(the_hash_algo, buf, len, type,
|
|
||||||
oid, header, &hdrlen);
|
|
||||||
|
|
||||||
if (!(flags & WRITE_OBJECT_FILE_PERSIST))
|
|
||||||
goto cleanup;
|
|
||||||
if (freshen_packed_object(oid) || freshen_loose_object(oid))
|
|
||||||
goto cleanup;
|
|
||||||
status = write_loose_object(oid, header, hdrlen, buf, len, 0, 0);
|
|
||||||
if (compat_type != -1)
|
|
||||||
return repo_add_loose_object_map(repo, oid, &compat_oid);
|
|
||||||
|
|
||||||
cleanup:
|
|
||||||
free(header);
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
|
|
||||||
int force_object_loose(const struct object_id *oid, time_t mtime)
|
int force_object_loose(const struct object_id *oid, time_t mtime)
|
||||||
{
|
{
|
||||||
struct repository *repo = the_repository;
|
struct repository *repo = the_repository;
|
||||||
|
@ -1682,8 +1579,7 @@ int read_loose_object(const char *path,
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
|
if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr)) != ULHR_OK) {
|
||||||
NULL) != ULHR_OK) {
|
|
||||||
error(_("unable to unpack header of %s"), path);
|
error(_("unable to unpack header of %s"), path);
|
||||||
goto out_inflate;
|
goto out_inflate;
|
||||||
}
|
}
|
||||||
|
@ -1693,6 +1589,12 @@ int read_loose_object(const char *path,
|
||||||
goto out_inflate;
|
goto out_inflate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (*oi->typep < 0) {
|
||||||
|
error(_("unable to parse type from header '%s' of %s"),
|
||||||
|
hdr, path);
|
||||||
|
goto out_inflate;
|
||||||
|
}
|
||||||
|
|
||||||
if (*oi->typep == OBJ_BLOB &&
|
if (*oi->typep == OBJ_BLOB &&
|
||||||
*size > repo_settings_get_big_file_threshold(the_repository)) {
|
*size > repo_settings_get_big_file_threshold(the_repository)) {
|
||||||
if (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)
|
if (check_stream_oid(&stream, hdr, *size, path, expected_oid) < 0)
|
||||||
|
@ -1703,9 +1605,9 @@ int read_loose_object(const char *path,
|
||||||
error(_("unable to unpack contents of %s"), path);
|
error(_("unable to unpack contents of %s"), path);
|
||||||
goto out_inflate;
|
goto out_inflate;
|
||||||
}
|
}
|
||||||
hash_object_file_literally(the_repository->hash_algo,
|
hash_object_file(the_repository->hash_algo,
|
||||||
*contents, *size,
|
*contents, *size,
|
||||||
oi->type_name->buf, real_oid);
|
*oi->typep, real_oid);
|
||||||
if (!oideq(expected_oid, real_oid))
|
if (!oideq(expected_oid, real_oid))
|
||||||
goto out_inflate;
|
goto out_inflate;
|
||||||
}
|
}
|
||||||
|
|
|
@ -133,12 +133,7 @@ int format_object_header(char *str, size_t size, enum object_type type,
|
||||||
* - ULHR_BAD on error
|
* - ULHR_BAD on error
|
||||||
* - ULHR_TOO_LONG if the header was too long
|
* - ULHR_TOO_LONG if the header was too long
|
||||||
*
|
*
|
||||||
* It will only parse up to MAX_HEADER_LEN bytes unless an optional
|
* It will only parse up to MAX_HEADER_LEN bytes.
|
||||||
* "hdrbuf" argument is non-NULL. This is intended for use with
|
|
||||||
* OBJECT_INFO_ALLOW_UNKNOWN_TYPE to extract the bad type for (error)
|
|
||||||
* reporting. The full header will be extracted to "hdrbuf" for use
|
|
||||||
* with parse_loose_header(), ULHR_TOO_LONG will still be returned
|
|
||||||
* from this function to indicate that the header was too long.
|
|
||||||
*/
|
*/
|
||||||
enum unpack_loose_header_result {
|
enum unpack_loose_header_result {
|
||||||
ULHR_OK,
|
ULHR_OK,
|
||||||
|
@ -149,8 +144,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
|
||||||
unsigned char *map,
|
unsigned char *map,
|
||||||
unsigned long mapsize,
|
unsigned long mapsize,
|
||||||
void *buffer,
|
void *buffer,
|
||||||
unsigned long bufsiz,
|
unsigned long bufsiz);
|
||||||
struct strbuf *hdrbuf);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* parse_loose_header() parses the starting "<type> <len>\0" of an
|
* parse_loose_header() parses the starting "<type> <len>\0" of an
|
||||||
|
@ -165,7 +159,7 @@ int parse_loose_header(const char *hdr, struct object_info *oi);
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
/*
|
/*
|
||||||
* By default, `write_object_file_literally()` does not actually write
|
* By default, `write_object_file()` does not actually write
|
||||||
* anything into the object store, but only computes the object ID.
|
* anything into the object store, but only computes the object ID.
|
||||||
* This flag changes that so that the object will be written as a loose
|
* This flag changes that so that the object will be written as a loose
|
||||||
* object and persisted.
|
* object and persisted.
|
||||||
|
@ -180,7 +174,7 @@ enum {
|
||||||
|
|
||||||
int write_object_file_flags(const void *buf, unsigned long len,
|
int write_object_file_flags(const void *buf, unsigned long len,
|
||||||
enum object_type type, struct object_id *oid,
|
enum object_type type, struct object_id *oid,
|
||||||
struct object_id *comapt_oid_in, unsigned flags);
|
struct object_id *compat_oid_in, unsigned flags);
|
||||||
static inline int write_object_file(const void *buf, unsigned long len,
|
static inline int write_object_file(const void *buf, unsigned long len,
|
||||||
enum object_type type, struct object_id *oid)
|
enum object_type type, struct object_id *oid)
|
||||||
{
|
{
|
||||||
|
@ -193,9 +187,6 @@ struct input_stream {
|
||||||
int is_finished;
|
int is_finished;
|
||||||
};
|
};
|
||||||
|
|
||||||
int write_object_file_literally(const void *buf, unsigned long len,
|
|
||||||
const char *type, struct object_id *oid,
|
|
||||||
unsigned flags);
|
|
||||||
int stream_loose_object(struct input_stream *in_stream, size_t len,
|
int stream_loose_object(struct input_stream *in_stream, size_t len,
|
||||||
struct object_id *oid);
|
struct object_id *oid);
|
||||||
|
|
||||||
|
|
|
@ -646,8 +646,6 @@ static int do_oid_object_info_extended(struct repository *r,
|
||||||
*(oi->disk_sizep) = 0;
|
*(oi->disk_sizep) = 0;
|
||||||
if (oi->delta_base_oid)
|
if (oi->delta_base_oid)
|
||||||
oidclr(oi->delta_base_oid, the_repository->hash_algo);
|
oidclr(oi->delta_base_oid, the_repository->hash_algo);
|
||||||
if (oi->type_name)
|
|
||||||
strbuf_addstr(oi->type_name, type_name(co->type));
|
|
||||||
if (oi->contentp)
|
if (oi->contentp)
|
||||||
*oi->contentp = xmemdupz(co->buf, co->size);
|
*oi->contentp = xmemdupz(co->buf, co->size);
|
||||||
oi->whence = OI_CACHED;
|
oi->whence = OI_CACHED;
|
||||||
|
@ -727,7 +725,7 @@ static int oid_object_info_convert(struct repository *r,
|
||||||
{
|
{
|
||||||
const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo];
|
const struct git_hash_algo *input_algo = &hash_algos[input_oid->algo];
|
||||||
int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT;
|
int do_die = flags & OBJECT_INFO_DIE_IF_CORRUPT;
|
||||||
struct strbuf type_name = STRBUF_INIT;
|
enum object_type type;
|
||||||
struct object_id oid, delta_base_oid;
|
struct object_id oid, delta_base_oid;
|
||||||
struct object_info new_oi, *oi;
|
struct object_info new_oi, *oi;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
|
@ -753,7 +751,7 @@ static int oid_object_info_convert(struct repository *r,
|
||||||
if (input_oi->sizep || input_oi->contentp) {
|
if (input_oi->sizep || input_oi->contentp) {
|
||||||
new_oi.contentp = &content;
|
new_oi.contentp = &content;
|
||||||
new_oi.sizep = &size;
|
new_oi.sizep = &size;
|
||||||
new_oi.type_name = &type_name;
|
new_oi.typep = &type;
|
||||||
}
|
}
|
||||||
oi = &new_oi;
|
oi = &new_oi;
|
||||||
}
|
}
|
||||||
|
@ -766,12 +764,7 @@ static int oid_object_info_convert(struct repository *r,
|
||||||
|
|
||||||
if (new_oi.contentp) {
|
if (new_oi.contentp) {
|
||||||
struct strbuf outbuf = STRBUF_INIT;
|
struct strbuf outbuf = STRBUF_INIT;
|
||||||
enum object_type type;
|
|
||||||
|
|
||||||
type = type_from_string_gently(type_name.buf, type_name.len,
|
|
||||||
!do_die);
|
|
||||||
if (type == -1)
|
|
||||||
return -1;
|
|
||||||
if (type != OBJ_BLOB) {
|
if (type != OBJ_BLOB) {
|
||||||
ret = convert_object_file(the_repository, &outbuf,
|
ret = convert_object_file(the_repository, &outbuf,
|
||||||
the_hash_algo, input_algo,
|
the_hash_algo, input_algo,
|
||||||
|
@ -788,10 +781,8 @@ static int oid_object_info_convert(struct repository *r,
|
||||||
*input_oi->contentp = content;
|
*input_oi->contentp = content;
|
||||||
else
|
else
|
||||||
free(content);
|
free(content);
|
||||||
if (input_oi->type_name)
|
if (input_oi->typep)
|
||||||
*input_oi->type_name = type_name;
|
*input_oi->typep = type;
|
||||||
else
|
|
||||||
strbuf_release(&type_name);
|
|
||||||
}
|
}
|
||||||
if (new_oi.delta_base_oid == &delta_base_oid) {
|
if (new_oi.delta_base_oid == &delta_base_oid) {
|
||||||
if (repo_oid_to_algop(r, &delta_base_oid, input_algo,
|
if (repo_oid_to_algop(r, &delta_base_oid, input_algo,
|
||||||
|
|
|
@ -206,7 +206,6 @@ struct object_info {
|
||||||
unsigned long *sizep;
|
unsigned long *sizep;
|
||||||
off_t *disk_sizep;
|
off_t *disk_sizep;
|
||||||
struct object_id *delta_base_oid;
|
struct object_id *delta_base_oid;
|
||||||
struct strbuf *type_name;
|
|
||||||
void **contentp;
|
void **contentp;
|
||||||
|
|
||||||
/* Response */
|
/* Response */
|
||||||
|
@ -241,8 +240,6 @@ struct object_info {
|
||||||
|
|
||||||
/* Invoke lookup_replace_object() on the given hash */
|
/* Invoke lookup_replace_object() on the given hash */
|
||||||
#define OBJECT_INFO_LOOKUP_REPLACE 1
|
#define OBJECT_INFO_LOOKUP_REPLACE 1
|
||||||
/* Allow reading from a loose object file of unknown/bogus type */
|
|
||||||
#define OBJECT_INFO_ALLOW_UNKNOWN_TYPE 2
|
|
||||||
/* Do not retry packed storage after checking packed and loose storage */
|
/* Do not retry packed storage after checking packed and loose storage */
|
||||||
#define OBJECT_INFO_QUICK 8
|
#define OBJECT_INFO_QUICK 8
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -1598,17 +1598,12 @@ int packed_object_info(struct repository *r, struct packed_git *p,
|
||||||
*oi->disk_sizep = pack_pos_to_offset(p, pos + 1) - obj_offset;
|
*oi->disk_sizep = pack_pos_to_offset(p, pos + 1) - obj_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (oi->typep || oi->type_name) {
|
if (oi->typep) {
|
||||||
enum object_type ptot;
|
enum object_type ptot;
|
||||||
ptot = packed_to_object_type(r, p, obj_offset,
|
ptot = packed_to_object_type(r, p, obj_offset,
|
||||||
type, &w_curs, curpos);
|
type, &w_curs, curpos);
|
||||||
if (oi->typep)
|
if (oi->typep)
|
||||||
*oi->typep = ptot;
|
*oi->typep = ptot;
|
||||||
if (oi->type_name) {
|
|
||||||
const char *tn = type_name(ptot);
|
|
||||||
if (tn)
|
|
||||||
strbuf_addstr(oi->type_name, tn);
|
|
||||||
}
|
|
||||||
if (ptot < 0) {
|
if (ptot < 0) {
|
||||||
type = OBJ_BAD;
|
type = OBJ_BAD;
|
||||||
goto out;
|
goto out;
|
||||||
|
|
|
@ -238,7 +238,7 @@ static int open_istream_loose(struct git_istream *st, struct repository *r,
|
||||||
return -1;
|
return -1;
|
||||||
switch (unpack_loose_header(&st->z, st->u.loose.mapped,
|
switch (unpack_loose_header(&st->z, st->u.loose.mapped,
|
||||||
st->u.loose.mapsize, st->u.loose.hdr,
|
st->u.loose.mapsize, st->u.loose.hdr,
|
||||||
sizeof(st->u.loose.hdr), NULL)) {
|
sizeof(st->u.loose.hdr))) {
|
||||||
case ULHR_OK:
|
case ULHR_OK:
|
||||||
break;
|
break;
|
||||||
case ULHR_BAD:
|
case ULHR_BAD:
|
||||||
|
|
|
@ -77,6 +77,7 @@ test_tool_sources = [
|
||||||
'test-windows-named-pipe.c',
|
'test-windows-named-pipe.c',
|
||||||
'test-write-cache.c',
|
'test-write-cache.c',
|
||||||
'test-xml-encode.c',
|
'test-xml-encode.c',
|
||||||
|
'test-zlib.c',
|
||||||
]
|
]
|
||||||
|
|
||||||
test_tool = executable('test-tool',
|
test_tool = executable('test-tool',
|
||||||
|
|
|
@ -91,6 +91,7 @@ static struct test_cmd cmds[] = {
|
||||||
{ "windows-named-pipe", cmd__windows_named_pipe },
|
{ "windows-named-pipe", cmd__windows_named_pipe },
|
||||||
#endif
|
#endif
|
||||||
{ "write-cache", cmd__write_cache },
|
{ "write-cache", cmd__write_cache },
|
||||||
|
{ "zlib", cmd__zlib },
|
||||||
};
|
};
|
||||||
|
|
||||||
static NORETURN void die_usage(void)
|
static NORETURN void die_usage(void)
|
||||||
|
|
|
@ -84,6 +84,7 @@ int cmd__wildmatch(int argc, const char **argv);
|
||||||
int cmd__windows_named_pipe(int argc, const char **argv);
|
int cmd__windows_named_pipe(int argc, const char **argv);
|
||||||
#endif
|
#endif
|
||||||
int cmd__write_cache(int argc, const char **argv);
|
int cmd__write_cache(int argc, const char **argv);
|
||||||
|
int cmd__zlib(int argc, const char **argv);
|
||||||
|
|
||||||
int cmd_hash_impl(int ac, const char **av, int algo, int unsafe);
|
int cmd_hash_impl(int ac, const char **av, int algo, int unsafe);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,62 @@
|
||||||
|
#include "test-tool.h"
|
||||||
|
#include "git-zlib.h"
|
||||||
|
#include "strbuf.h"
|
||||||
|
|
||||||
|
static const char *zlib_usage = "test-tool zlib [inflate|deflate]";
|
||||||
|
|
||||||
|
static void do_zlib(struct git_zstream *stream,
|
||||||
|
int (*zlib_func)(git_zstream *, int),
|
||||||
|
int fd_in, int fd_out)
|
||||||
|
{
|
||||||
|
struct strbuf buf_in = STRBUF_INIT;
|
||||||
|
int status = Z_OK;
|
||||||
|
|
||||||
|
if (strbuf_read(&buf_in, fd_in, 0) < 0)
|
||||||
|
die_errno("read error");
|
||||||
|
|
||||||
|
stream->next_in = (unsigned char *)buf_in.buf;
|
||||||
|
stream->avail_in = buf_in.len;
|
||||||
|
|
||||||
|
while (status == Z_OK ||
|
||||||
|
(status == Z_BUF_ERROR && !stream->avail_out)) {
|
||||||
|
unsigned char buf_out[4096];
|
||||||
|
|
||||||
|
stream->next_out = buf_out;
|
||||||
|
stream->avail_out = sizeof(buf_out);
|
||||||
|
|
||||||
|
status = zlib_func(stream, Z_FINISH);
|
||||||
|
if (write_in_full(fd_out, buf_out,
|
||||||
|
sizeof(buf_out) - stream->avail_out) < 0)
|
||||||
|
die_errno("write error");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != Z_STREAM_END)
|
||||||
|
die("zlib error %d", status);
|
||||||
|
|
||||||
|
strbuf_release(&buf_in);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd__zlib(int argc, const char **argv)
|
||||||
|
{
|
||||||
|
git_zstream stream;
|
||||||
|
|
||||||
|
if (argc != 2)
|
||||||
|
usage(zlib_usage);
|
||||||
|
|
||||||
|
memset(&stream, 0, sizeof(stream));
|
||||||
|
|
||||||
|
if (!strcmp(argv[1], "inflate")) {
|
||||||
|
git_inflate_init(&stream);
|
||||||
|
do_zlib(&stream, git_inflate, 0, 1);
|
||||||
|
git_inflate_end(&stream);
|
||||||
|
} else if (!strcmp(argv[1], "deflate")) {
|
||||||
|
git_deflate_init(&stream, Z_DEFAULT_COMPRESSION);
|
||||||
|
do_zlib(&stream, git_deflate, 0, 1);
|
||||||
|
git_deflate_end(&stream);
|
||||||
|
} else {
|
||||||
|
error("unknown mode: %s", argv[1]);
|
||||||
|
usage(zlib_usage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
# Support routines for hand-crafting loose objects.
|
||||||
|
|
||||||
|
# Write a loose object into the odb at $1, with object type $2 and contents
|
||||||
|
# from stdin. Writes the oid to stdout. Example:
|
||||||
|
#
|
||||||
|
# oid=$(echo foo | loose_obj .git/objects blob)
|
||||||
|
#
|
||||||
|
loose_obj () {
|
||||||
|
cat >tmp_loose.content &&
|
||||||
|
size=$(wc -c <tmp_loose.content) &&
|
||||||
|
{
|
||||||
|
# Do not quote $size here; we want the shell
|
||||||
|
# to strip whitespace that "wc" adds on some platforms.
|
||||||
|
printf "%s %s\0" "$2" $size &&
|
||||||
|
cat tmp_loose.content
|
||||||
|
} >tmp_loose.raw &&
|
||||||
|
|
||||||
|
oid=$(test-tool $test_hash_algo <tmp_loose.raw) &&
|
||||||
|
suffix=${oid#??} &&
|
||||||
|
prefix=${oid%$suffix} &&
|
||||||
|
dir=$1/$prefix &&
|
||||||
|
file=$dir/$suffix &&
|
||||||
|
|
||||||
|
test-tool zlib deflate <tmp_loose.raw >tmp_loose.zlib &&
|
||||||
|
mkdir -p "$dir" &&
|
||||||
|
mv tmp_loose.zlib "$file" &&
|
||||||
|
|
||||||
|
rm tmp_loose.raw tmp_loose.content &&
|
||||||
|
echo "$oid"
|
||||||
|
}
|
|
@ -3,6 +3,7 @@
|
||||||
test_description='git cat-file'
|
test_description='git cat-file'
|
||||||
|
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
. "$TEST_DIRECTORY/lib-loose.sh"
|
||||||
|
|
||||||
test_cmdmode_usage () {
|
test_cmdmode_usage () {
|
||||||
test_expect_code 129 "$@" 2>err &&
|
test_expect_code 129 "$@" 2>err &&
|
||||||
|
@ -136,18 +137,6 @@ $content"
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "Type of $type is correct using --allow-unknown-type" '
|
|
||||||
echo $type >expect &&
|
|
||||||
git cat-file -t --allow-unknown-type $oid >actual &&
|
|
||||||
test_cmp expect actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success "Size of $type is correct using --allow-unknown-type" '
|
|
||||||
echo $size >expect &&
|
|
||||||
git cat-file -s --allow-unknown-type $oid >actual &&
|
|
||||||
test_cmp expect actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test -z "$content" ||
|
test -z "$content" ||
|
||||||
test_expect_success "Content of $type is correct" '
|
test_expect_success "Content of $type is correct" '
|
||||||
echo_without_newline "$content" >expect &&
|
echo_without_newline "$content" >expect &&
|
||||||
|
@ -669,41 +658,28 @@ test_expect_success 'setup bogus data' '
|
||||||
bogus_short_type="bogus" &&
|
bogus_short_type="bogus" &&
|
||||||
bogus_short_content="bogus" &&
|
bogus_short_content="bogus" &&
|
||||||
bogus_short_size=$(strlen "$bogus_short_content") &&
|
bogus_short_size=$(strlen "$bogus_short_content") &&
|
||||||
bogus_short_oid=$(echo_without_newline "$bogus_short_content" | git hash-object -t $bogus_short_type --literally -w --stdin) &&
|
bogus_short_oid=$(echo_without_newline "$bogus_short_content" | loose_obj .git/objects $bogus_short_type) &&
|
||||||
|
|
||||||
bogus_long_type="abcdefghijklmnopqrstuvwxyz1234679" &&
|
bogus_long_type="abcdefghijklmnopqrstuvwxyz1234679" &&
|
||||||
bogus_long_content="bogus" &&
|
bogus_long_content="bogus" &&
|
||||||
bogus_long_size=$(strlen "$bogus_long_content") &&
|
bogus_long_size=$(strlen "$bogus_long_content") &&
|
||||||
bogus_long_oid=$(echo_without_newline "$bogus_long_content" | git hash-object -t $bogus_long_type --literally -w --stdin)
|
bogus_long_oid=$(echo_without_newline "$bogus_long_content" | loose_obj .git/objects $bogus_long_type)
|
||||||
'
|
'
|
||||||
|
|
||||||
for arg1 in '' --allow-unknown-type
|
for arg1 in -s -t -p
|
||||||
do
|
do
|
||||||
for arg2 in -s -t -p
|
test_expect_success "cat-file $arg1 error on bogus short OID" '
|
||||||
do
|
|
||||||
if test "$arg1" = "--allow-unknown-type" && test "$arg2" = "-p"
|
|
||||||
then
|
|
||||||
continue
|
|
||||||
fi
|
|
||||||
|
|
||||||
|
|
||||||
test_expect_success "cat-file $arg1 $arg2 error on bogus short OID" '
|
|
||||||
cat >expect <<-\EOF &&
|
cat >expect <<-\EOF &&
|
||||||
fatal: invalid object type
|
fatal: invalid object type
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
if test "$arg1" = "--allow-unknown-type"
|
test_must_fail git cat-file $arg1 $bogus_short_oid >out 2>actual &&
|
||||||
then
|
|
||||||
git cat-file $arg1 $arg2 $bogus_short_oid
|
|
||||||
else
|
|
||||||
test_must_fail git cat-file $arg1 $arg2 $bogus_short_oid >out 2>actual &&
|
|
||||||
test_must_be_empty out &&
|
test_must_be_empty out &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
fi
|
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "cat-file $arg1 $arg2 error on bogus full OID" '
|
test_expect_success "cat-file $arg1 error on bogus full OID" '
|
||||||
if test "$arg2" = "-p"
|
if test "$arg1" = "-p"
|
||||||
then
|
then
|
||||||
cat >expect <<-EOF
|
cat >expect <<-EOF
|
||||||
error: header for $bogus_long_oid too long, exceeds 32 bytes
|
error: header for $bogus_long_oid too long, exceeds 32 bytes
|
||||||
|
@ -716,27 +692,22 @@ do
|
||||||
EOF
|
EOF
|
||||||
fi &&
|
fi &&
|
||||||
|
|
||||||
if test "$arg1" = "--allow-unknown-type"
|
test_must_fail git cat-file $arg1 $bogus_long_oid >out 2>actual &&
|
||||||
then
|
|
||||||
git cat-file $arg1 $arg2 $bogus_short_oid
|
|
||||||
else
|
|
||||||
test_must_fail git cat-file $arg1 $arg2 $bogus_long_oid >out 2>actual &&
|
|
||||||
test_must_be_empty out &&
|
test_must_be_empty out &&
|
||||||
test_cmp expect actual
|
test_cmp expect actual
|
||||||
fi
|
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "cat-file $arg1 $arg2 error on missing short OID" '
|
test_expect_success "cat-file $arg1 error on missing short OID" '
|
||||||
cat >expect.err <<-EOF &&
|
cat >expect.err <<-EOF &&
|
||||||
fatal: Not a valid object name $(test_oid deadbeef_short)
|
fatal: Not a valid object name $(test_oid deadbeef_short)
|
||||||
EOF
|
EOF
|
||||||
test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual &&
|
test_must_fail git cat-file $arg1 $(test_oid deadbeef_short) >out 2>err.actual &&
|
||||||
test_must_be_empty out &&
|
test_must_be_empty out &&
|
||||||
test_cmp expect.err err.actual
|
test_cmp expect.err err.actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success "cat-file $arg1 $arg2 error on missing full OID" '
|
test_expect_success "cat-file $arg1 error on missing full OID" '
|
||||||
if test "$arg2" = "-p"
|
if test "$arg1" = "-p"
|
||||||
then
|
then
|
||||||
cat >expect.err <<-EOF
|
cat >expect.err <<-EOF
|
||||||
fatal: Not a valid object name $(test_oid deadbeef)
|
fatal: Not a valid object name $(test_oid deadbeef)
|
||||||
|
@ -746,26 +717,16 @@ do
|
||||||
fatal: git cat-file: could not get object info
|
fatal: git cat-file: could not get object info
|
||||||
EOF
|
EOF
|
||||||
fi &&
|
fi &&
|
||||||
test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef) >out 2>err.actual &&
|
test_must_fail git cat-file $arg1 $(test_oid deadbeef) >out 2>err.actual &&
|
||||||
test_must_be_empty out &&
|
test_must_be_empty out &&
|
||||||
test_cmp expect.err err.actual
|
test_cmp expect.err err.actual
|
||||||
'
|
'
|
||||||
done
|
done
|
||||||
done
|
|
||||||
|
|
||||||
test_expect_success '-e is OK with a broken object without --allow-unknown-type' '
|
test_expect_success '-e is OK with a broken object' '
|
||||||
git cat-file -e $bogus_short_oid
|
git cat-file -e $bogus_short_oid
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '-e can not be combined with --allow-unknown-type' '
|
|
||||||
test_expect_code 128 git cat-file -e --allow-unknown-type $bogus_short_oid
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success '-p cannot print a broken object even with --allow-unknown-type' '
|
|
||||||
test_must_fail git cat-file -p $bogus_short_oid &&
|
|
||||||
test_expect_code 128 git cat-file -p --allow-unknown-type $bogus_short_oid
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success '<type> <hash> does not work with objects of broken types' '
|
test_expect_success '<type> <hash> does not work with objects of broken types' '
|
||||||
cat >err.expect <<-\EOF &&
|
cat >err.expect <<-\EOF &&
|
||||||
fatal: invalid object type "bogus"
|
fatal: invalid object type "bogus"
|
||||||
|
@ -788,60 +749,8 @@ test_expect_success 'broken types combined with --batch and --batch-check' '
|
||||||
test_cmp err.expect err.actual
|
test_cmp err.expect err.actual
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'the --batch and --batch-check options do not combine with --allow-unknown-type' '
|
test_expect_success 'clean up broken objects' '
|
||||||
test_expect_code 128 git cat-file --batch --allow-unknown-type <bogus-oid &&
|
rm .git/objects/$(test_oid_to_path $bogus_short_oid) &&
|
||||||
test_expect_code 128 git cat-file --batch-check --allow-unknown-type <bogus-oid
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'the --allow-unknown-type option does not consider replacement refs' '
|
|
||||||
cat >expect <<-EOF &&
|
|
||||||
$bogus_short_type
|
|
||||||
EOF
|
|
||||||
git cat-file -t --allow-unknown-type $bogus_short_oid >actual &&
|
|
||||||
test_cmp expect actual &&
|
|
||||||
|
|
||||||
# Create it manually, as "git replace" will die on bogus
|
|
||||||
# types.
|
|
||||||
head=$(git rev-parse --verify HEAD) &&
|
|
||||||
test_when_finished "test-tool ref-store main delete-refs 0 msg refs/replace/$bogus_short_oid" &&
|
|
||||||
test-tool ref-store main update-ref msg "refs/replace/$bogus_short_oid" $head $ZERO_OID REF_SKIP_OID_VERIFICATION &&
|
|
||||||
|
|
||||||
cat >expect <<-EOF &&
|
|
||||||
commit
|
|
||||||
EOF
|
|
||||||
git cat-file -t --allow-unknown-type $bogus_short_oid >actual &&
|
|
||||||
test_cmp expect actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success "Type of broken object is correct" '
|
|
||||||
echo $bogus_short_type >expect &&
|
|
||||||
git cat-file -t --allow-unknown-type $bogus_short_oid >actual &&
|
|
||||||
test_cmp expect actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success "Size of broken object is correct" '
|
|
||||||
echo $bogus_short_size >expect &&
|
|
||||||
git cat-file -s --allow-unknown-type $bogus_short_oid >actual &&
|
|
||||||
test_cmp expect actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'clean up broken object' '
|
|
||||||
rm .git/objects/$(test_oid_to_path $bogus_short_oid)
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success "Type of broken object is correct when type is large" '
|
|
||||||
echo $bogus_long_type >expect &&
|
|
||||||
git cat-file -t --allow-unknown-type $bogus_long_oid >actual &&
|
|
||||||
test_cmp expect actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success "Size of large broken object is correct when type is large" '
|
|
||||||
echo $bogus_long_size >expect &&
|
|
||||||
git cat-file -s --allow-unknown-type $bogus_long_oid >actual &&
|
|
||||||
test_cmp expect actual
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'clean up broken object' '
|
|
||||||
rm .git/objects/$(test_oid_to_path $bogus_long_oid)
|
rm .git/objects/$(test_oid_to_path $bogus_long_oid)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
@ -903,25 +812,6 @@ test_expect_success 'cat-file -t and -s on corrupt loose object' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'truncated object with --allow-unknown-type' - <<\EOT
|
|
||||||
objtype='a really long type name that exceeds the 32-byte limit' &&
|
|
||||||
blob=$(git hash-object -w --literally -t "$objtype" /dev/null) &&
|
|
||||||
objpath=.git/objects/$(test_oid_to_path "$blob") &&
|
|
||||||
|
|
||||||
# We want to truncate the object far enough in that we don't hit the
|
|
||||||
# end while inflating the first 32 bytes (since we want to have to dig
|
|
||||||
# for the trailing NUL of the header). But we don't want to go too far,
|
|
||||||
# since our header isn't very big. And of course we are counting
|
|
||||||
# deflated zlib bytes in the on-disk file, so it's a bit of a guess.
|
|
||||||
# Empirically 50 seems to work.
|
|
||||||
mv "$objpath" obj.bak &&
|
|
||||||
test_when_finished 'mv obj.bak "$objpath"' &&
|
|
||||||
test_copy_bytes 50 <obj.bak >"$objpath" &&
|
|
||||||
|
|
||||||
test_must_fail git cat-file --allow-unknown-type -t $blob 2>err &&
|
|
||||||
test_grep "unable to unpack $blob header" err
|
|
||||||
EOT
|
|
||||||
|
|
||||||
test_expect_success 'object reading handles zlib dictionary' - <<\EOT
|
test_expect_success 'object reading handles zlib dictionary' - <<\EOT
|
||||||
echo 'content that will be recompressed' >file &&
|
echo 'content that will be recompressed' >file &&
|
||||||
blob=$(git hash-object -w file) &&
|
blob=$(git hash-object -w file) &&
|
||||||
|
|
|
@ -248,15 +248,8 @@ test_expect_success 'hash-object complains about truncated type name' '
|
||||||
test_must_fail git hash-object -t bl --stdin </dev/null
|
test_must_fail git hash-object -t bl --stdin </dev/null
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '--literally' '
|
test_expect_success '--literally complains about non-standard types' '
|
||||||
t=1234567890 &&
|
test_must_fail git hash-object -t bogus --literally --stdin
|
||||||
echo example | git hash-object -t $t --literally --stdin
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success '--literally with extra-long type' '
|
|
||||||
t=12345678901234567890123456789012345678901234567890 &&
|
|
||||||
t="$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t$t" &&
|
|
||||||
echo example | git hash-object -t $t --literally --stdin
|
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success '--stdin outside of repository (uses SHA-1)' '
|
test_expect_success '--stdin outside of repository (uses SHA-1)' '
|
||||||
|
|
|
@ -7,6 +7,7 @@ test_description='git fsck random collection of tests
|
||||||
'
|
'
|
||||||
|
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
. "$TEST_DIRECTORY/lib-loose.sh"
|
||||||
|
|
||||||
test_expect_success setup '
|
test_expect_success setup '
|
||||||
git config gc.auto 0 &&
|
git config gc.auto 0 &&
|
||||||
|
@ -71,30 +72,6 @@ test_expect_success 'object with hash mismatch' '
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
test_expect_success 'object with hash and type mismatch' '
|
|
||||||
git init --bare hash-type-mismatch &&
|
|
||||||
(
|
|
||||||
cd hash-type-mismatch &&
|
|
||||||
|
|
||||||
oid=$(echo blob | git hash-object -w --stdin -t garbage --literally) &&
|
|
||||||
oldoid=$oid &&
|
|
||||||
old=$(test_oid_to_path "$oid") &&
|
|
||||||
new=$(dirname $old)/$(test_oid ff_2) &&
|
|
||||||
oid="$(dirname $new)$(basename $new)" &&
|
|
||||||
|
|
||||||
mv objects/$old objects/$new &&
|
|
||||||
git update-index --add --cacheinfo 100644 $oid foo &&
|
|
||||||
tree=$(git write-tree) &&
|
|
||||||
cmt=$(echo bogus | git commit-tree $tree) &&
|
|
||||||
git update-ref refs/heads/bogus $cmt &&
|
|
||||||
|
|
||||||
|
|
||||||
test_must_fail git fsck 2>out &&
|
|
||||||
grep "^error: $oldoid: hash-path mismatch, found at: .*$new" out &&
|
|
||||||
grep "^error: $oldoid: object is of unknown type '"'"'garbage'"'"'" out
|
|
||||||
)
|
|
||||||
'
|
|
||||||
|
|
||||||
test_expect_success 'zlib corrupt loose object output ' '
|
test_expect_success 'zlib corrupt loose object output ' '
|
||||||
git init --bare corrupt-loose-output &&
|
git init --bare corrupt-loose-output &&
|
||||||
(
|
(
|
||||||
|
@ -997,12 +974,13 @@ test_expect_success 'fsck error and recovery on invalid object type' '
|
||||||
(
|
(
|
||||||
cd garbage-type &&
|
cd garbage-type &&
|
||||||
|
|
||||||
garbage_blob=$(git hash-object --stdin -w -t garbage --literally </dev/null) &&
|
garbage_blob=$(loose_obj objects garbage </dev/null) &&
|
||||||
|
|
||||||
test_must_fail git fsck 2>err &&
|
test_must_fail git fsck 2>err &&
|
||||||
grep -e "^error" -e "^fatal" err >errors &&
|
grep -e "^error" -e "^fatal" err >errors &&
|
||||||
test_line_count = 1 errors &&
|
test_line_count = 2 errors &&
|
||||||
grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err
|
test_grep "unable to parse type from header .garbage" err &&
|
||||||
|
test_grep "$garbage_blob: object corrupt or missing:" err
|
||||||
)
|
)
|
||||||
'
|
'
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME=main
|
||||||
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
export GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME
|
||||||
|
|
||||||
. ./test-lib.sh
|
. ./test-lib.sh
|
||||||
|
. "$TEST_DIRECTORY/lib-loose.sh"
|
||||||
|
|
||||||
test_cmp_failed_rev_parse () {
|
test_cmp_failed_rev_parse () {
|
||||||
dir=$1
|
dir=$1
|
||||||
|
@ -67,8 +68,8 @@ test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' '
|
||||||
cd blob.bad &&
|
cd blob.bad &&
|
||||||
|
|
||||||
# Both have the prefix "bad0"
|
# Both have the prefix "bad0"
|
||||||
echo xyzfaowcoh | git hash-object -t bad -w --stdin --literally &&
|
echo xyzfaowcoh | loose_obj objects bad &&
|
||||||
echo xyzhjpyvwl | git hash-object -t bad -w --stdin --literally
|
echo xyzhjpyvwl | loose_obj objects bad
|
||||||
) &&
|
) &&
|
||||||
|
|
||||||
test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF
|
test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF
|
||||||
|
|
Loading…
Reference in New Issue