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]
|
||||
'git cat-file' <type> <object>
|
||||
'git cat-file' (-e | -p) <object>
|
||||
'git cat-file' (-t | -s) [--allow-unknown-type] <object>
|
||||
'git cat-file' (-e | -p | -t | -s) <object>
|
||||
'git cat-file' (--textconv | --filters)
|
||||
[<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]
|
||||
'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
|
||||
repository.
|
||||
|
||||
--allow-unknown-type::
|
||||
Allow `-s` or `-t` to query broken/corrupt objects of unknown type.
|
||||
|
||||
--follow-symlinks::
|
||||
With `--batch` or `--batch-check`, follow symlinks inside the
|
||||
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-write-cache.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
|
||||
# them in TEST_BUILTINS_OBJS above.
|
||||
|
|
|
@ -100,8 +100,7 @@ static int stream_blob(const struct object_id *oid)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int cat_one_file(int opt, const char *exp_type, const char *obj_name,
|
||||
int unknown_type)
|
||||
static int cat_one_file(int opt, const char *exp_type, const char *obj_name)
|
||||
{
|
||||
int ret;
|
||||
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;
|
||||
struct object_context obj_context = {0};
|
||||
struct object_info oi = OBJECT_INFO_INIT;
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
unsigned flags = OBJECT_INFO_LOOKUP_REPLACE;
|
||||
unsigned get_oid_flags =
|
||||
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)
|
||||
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,
|
||||
&obj_context))
|
||||
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;
|
||||
switch (opt) {
|
||||
case 't':
|
||||
oi.type_name = &sb;
|
||||
oi.typep = &type;
|
||||
if (oid_object_info_extended(the_repository, &oid, &oi, flags) < 0)
|
||||
die("git cat-file: could not get object info");
|
||||
if (sb.len) {
|
||||
printf("%s\n", sb.buf);
|
||||
strbuf_release(&sb);
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
}
|
||||
break;
|
||||
printf("%s\n", type_name(type));
|
||||
ret = 0;
|
||||
goto cleanup;
|
||||
|
||||
case 's':
|
||||
oi.sizep = &size;
|
||||
|
@ -1038,8 +1029,7 @@ int cmd_cat_file(int argc,
|
|||
|
||||
const char * const builtin_catfile_usage[] = {
|
||||
N_("git cat-file <type> <object>"),
|
||||
N_("git cat-file (-e | -p) <object>"),
|
||||
N_("git cat-file (-t | -s) [--allow-unknown-type] <object>"),
|
||||
N_("git cat-file (-e | -p | -t | -s) <object>"),
|
||||
N_("git cat-file (--textconv | --filters)\n"
|
||||
" [<rev>:<path|tree-ish> | --path=<path|tree-ish> <rev>]"),
|
||||
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_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_BOOL(0, "allow-unknown-type", &unknown_type,
|
||||
N_("allow -s and -t to work with broken/corrupt objects")),
|
||||
OPT_HIDDEN_BOOL(0, "allow-unknown-type", &unknown_type,
|
||||
N_("historical option -- no-op")),
|
||||
OPT_BOOL(0, "use-mailmap", &use_mailmap, N_("use mail map file")),
|
||||
OPT_ALIAS(0, "mailmap", "use-mailmap"),
|
||||
/* Batch mode */
|
||||
|
@ -1209,10 +1199,7 @@ int cmd_cat_file(int argc,
|
|||
obj_name = argv[1];
|
||||
}
|
||||
|
||||
if (unknown_type && opt != 't' && opt != 's')
|
||||
die("git cat-file --allow-unknown-type: use with -s or -t");
|
||||
|
||||
ret = cat_one_file(opt, exp_type, obj_name, unknown_type);
|
||||
ret = cat_one_file(opt, exp_type, obj_name);
|
||||
|
||||
out:
|
||||
list_objects_filter_release(&batch.objects_filter);
|
||||
|
|
|
@ -614,12 +614,11 @@ static void get_default_heads(void)
|
|||
struct for_each_loose_cb
|
||||
{
|
||||
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;
|
||||
enum object_type type = OBJ_NONE;
|
||||
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);
|
||||
int err = 0;
|
||||
|
||||
strbuf_reset(&cb_data->obj_type);
|
||||
oi.type_name = &cb_data->obj_type;
|
||||
oi.sizep = &size;
|
||||
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"),
|
||||
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) {
|
||||
errors_found |= ERROR_OBJECT;
|
||||
free(contents);
|
||||
|
@ -697,7 +690,6 @@ static void fsck_object_dir(const char *path)
|
|||
{
|
||||
struct progress *progress = NULL;
|
||||
struct for_each_loose_cb cb_data = {
|
||||
.obj_type = STRBUF_INIT,
|
||||
.progress = progress,
|
||||
};
|
||||
|
||||
|
@ -712,7 +704,6 @@ static void fsck_object_dir(const char *path)
|
|||
&cb_data);
|
||||
display_progress(progress, 256);
|
||||
stop_progress(&progress);
|
||||
strbuf_release(&cb_data.obj_type);
|
||||
}
|
||||
|
||||
static int fsck_head_link(const char *head_ref_name,
|
||||
|
|
|
@ -19,49 +19,15 @@
|
|||
#include "strbuf.h"
|
||||
#include "write-or-die.h"
|
||||
|
||||
enum {
|
||||
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)
|
||||
static void hash_fd(int fd, const char *type, const char *path, 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 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 ||
|
||||
(literally
|
||||
? hash_literally(&oid, fd, type, flags)
|
||||
: index_fd(the_repository->index, &oid, fd, &st,
|
||||
type_from_string(type), path, index_flags)))
|
||||
die((flags & HASH_OBJECT_WRITE)
|
||||
index_fd(the_repository->index, &oid, fd, &st,
|
||||
type_from_string(type), path, flags))
|
||||
die((flags & INDEX_WRITE_OBJECT)
|
||||
? "Unable to add %s to database"
|
||||
: "Unable to hash %s", path);
|
||||
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,
|
||||
unsigned flags, int literally)
|
||||
unsigned flags)
|
||||
{
|
||||
int fd;
|
||||
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,
|
||||
int literally)
|
||||
static void hash_stdin_paths(const char *type, int no_filters, unsigned flags)
|
||||
{
|
||||
struct strbuf buf = 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");
|
||||
strbuf_swap(&buf, &unquoted);
|
||||
}
|
||||
hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags,
|
||||
literally);
|
||||
hash_object(buf.buf, type, no_filters ? NULL : buf.buf, flags);
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
strbuf_release(&unquoted);
|
||||
|
@ -111,19 +75,20 @@ int cmd_hash_object(int argc,
|
|||
int hashstdin = 0;
|
||||
int stdin_paths = 0;
|
||||
int no_filters = 0;
|
||||
int literally = 0;
|
||||
int nongit = 0;
|
||||
unsigned flags = HASH_OBJECT_CHECK;
|
||||
unsigned flags = INDEX_FORMAT_CHECK;
|
||||
const char *vpath = NULL;
|
||||
char *vpath_free = NULL;
|
||||
const struct option hash_object_options[] = {
|
||||
OPT_STRING('t', NULL, &type, N_("type"), N_("object type")),
|
||||
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_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, "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_END()
|
||||
};
|
||||
|
@ -133,7 +98,7 @@ int cmd_hash_object(int argc,
|
|||
argc = parse_options(argc, argv, prefix, hash_object_options,
|
||||
hash_object_usage, 0);
|
||||
|
||||
if (flags & HASH_OBJECT_WRITE)
|
||||
if (flags & INDEX_WRITE_OBJECT)
|
||||
prefix = setup_git_directory();
|
||||
else
|
||||
prefix = setup_git_directory_gently(&nongit);
|
||||
|
@ -169,7 +134,7 @@ int cmd_hash_object(int argc,
|
|||
}
|
||||
|
||||
if (hashstdin)
|
||||
hash_fd(0, type, vpath, flags, literally);
|
||||
hash_fd(0, type, vpath, flags);
|
||||
|
||||
for (i = 0 ; i < argc; i++) {
|
||||
const char *arg = argv[i];
|
||||
|
@ -178,12 +143,12 @@ int cmd_hash_object(int argc,
|
|||
if (prefix)
|
||||
arg = to_free = prefix_filename(prefix, arg);
|
||||
hash_object(arg, type, no_filters ? NULL : vpath ? vpath : arg,
|
||||
flags, literally);
|
||||
flags);
|
||||
free(to_free);
|
||||
}
|
||||
|
||||
if (stdin_paths)
|
||||
hash_stdin_paths(type, no_filters, flags, literally);
|
||||
hash_stdin_paths(type, no_filters, flags);
|
||||
|
||||
free(vpath_free);
|
||||
|
||||
|
|
142
object-file.c
142
object-file.c
|
@ -130,12 +130,6 @@ int has_loose_object(const struct object_id *oid)
|
|||
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,
|
||||
size_t objsize)
|
||||
{
|
||||
|
@ -144,7 +138,7 @@ int format_object_header(char *str, size_t size, enum object_type type,
|
|||
if (!name)
|
||||
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,
|
||||
|
@ -299,8 +293,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
|
|||
unsigned char *map,
|
||||
unsigned long mapsize,
|
||||
void *buffer,
|
||||
unsigned long bufsiz,
|
||||
struct strbuf *header)
|
||||
unsigned long bufsiz)
|
||||
{
|
||||
int status;
|
||||
|
||||
|
@ -325,32 +318,9 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
|
|||
return ULHR_OK;
|
||||
|
||||
/*
|
||||
* We have a header longer than MAX_HEADER_LEN. The "header"
|
||||
* here is only non-NULL when we run "cat-file
|
||||
* --allow-unknown-type".
|
||||
* We have a header longer than MAX_HEADER_LEN.
|
||||
*/
|
||||
if (!header)
|
||||
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;
|
||||
return ULHR_TOO_LONG;
|
||||
}
|
||||
|
||||
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);
|
||||
if (oi->type_name)
|
||||
strbuf_add(oi->type_name, type_buf, type_len);
|
||||
if (oi->typep)
|
||||
*oi->typep = type;
|
||||
|
||||
|
@ -476,10 +444,8 @@ int loose_object_info(struct repository *r,
|
|||
void *map;
|
||||
git_zstream stream;
|
||||
char hdr[MAX_HEADER_LEN];
|
||||
struct strbuf hdrbuf = STRBUF_INIT;
|
||||
unsigned long size_scratch;
|
||||
enum object_type type_scratch;
|
||||
int allow_unknown = flags & OBJECT_INFO_ALLOW_UNKNOWN_TYPE;
|
||||
|
||||
if (oi->delta_base_oid)
|
||||
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
|
||||
* object even exists.
|
||||
*/
|
||||
if (!oi->typep && !oi->type_name && !oi->sizep && !oi->contentp) {
|
||||
if (!oi->typep && !oi->sizep && !oi->contentp) {
|
||||
struct stat st;
|
||||
if (!oi->disk_sizep && (flags & OBJECT_INFO_QUICK))
|
||||
return quick_has_loose(r, oid) ? 0 : -1;
|
||||
|
@ -521,18 +487,15 @@ int loose_object_info(struct repository *r,
|
|||
if (oi->disk_sizep)
|
||||
*oi->disk_sizep = mapsize;
|
||||
|
||||
switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
|
||||
allow_unknown ? &hdrbuf : NULL)) {
|
||||
switch (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr))) {
|
||||
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));
|
||||
else if (!allow_unknown && *oi->typep < 0)
|
||||
else if (*oi->typep < 0)
|
||||
die(_("invalid object type"));
|
||||
|
||||
if (!oi->contentp)
|
||||
break;
|
||||
if (hdrbuf.len)
|
||||
BUG("unpacking content with unknown types not yet supported");
|
||||
*oi->contentp = unpack_loose_rest(&stream, hdr, *oi->sizep, oid);
|
||||
if (*oi->contentp)
|
||||
goto cleanup;
|
||||
|
@ -558,7 +521,6 @@ cleanup:
|
|||
munmap(map, mapsize);
|
||||
if (oi->sizep == &size_scratch)
|
||||
oi->sizep = NULL;
|
||||
strbuf_release(&hdrbuf);
|
||||
if (oi->typep == &type_scratch)
|
||||
oi->typep = NULL;
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
static int check_collision(const char *source, const char *dest)
|
||||
|
@ -730,21 +681,14 @@ out:
|
|||
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,
|
||||
unsigned long len, enum object_type type,
|
||||
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. */
|
||||
|
@ -1146,53 +1090,6 @@ int write_object_file_flags(const void *buf, unsigned long len,
|
|||
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)
|
||||
{
|
||||
struct repository *repo = the_repository;
|
||||
|
@ -1682,8 +1579,7 @@ int read_loose_object(const char *path,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr),
|
||||
NULL) != ULHR_OK) {
|
||||
if (unpack_loose_header(&stream, map, mapsize, hdr, sizeof(hdr)) != ULHR_OK) {
|
||||
error(_("unable to unpack header of %s"), path);
|
||||
goto out_inflate;
|
||||
}
|
||||
|
@ -1693,6 +1589,12 @@ int read_loose_object(const char *path,
|
|||
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 &&
|
||||
*size > repo_settings_get_big_file_threshold(the_repository)) {
|
||||
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);
|
||||
goto out_inflate;
|
||||
}
|
||||
hash_object_file_literally(the_repository->hash_algo,
|
||||
*contents, *size,
|
||||
oi->type_name->buf, real_oid);
|
||||
hash_object_file(the_repository->hash_algo,
|
||||
*contents, *size,
|
||||
*oi->typep, real_oid);
|
||||
if (!oideq(expected_oid, real_oid))
|
||||
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_TOO_LONG if the header was too long
|
||||
*
|
||||
* It will only parse up to MAX_HEADER_LEN bytes unless an optional
|
||||
* "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.
|
||||
* It will only parse up to MAX_HEADER_LEN bytes.
|
||||
*/
|
||||
enum unpack_loose_header_result {
|
||||
ULHR_OK,
|
||||
|
@ -149,8 +144,7 @@ enum unpack_loose_header_result unpack_loose_header(git_zstream *stream,
|
|||
unsigned char *map,
|
||||
unsigned long mapsize,
|
||||
void *buffer,
|
||||
unsigned long bufsiz,
|
||||
struct strbuf *hdrbuf);
|
||||
unsigned long bufsiz);
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
/*
|
||||
* 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.
|
||||
* This flag changes that so that the object will be written as a loose
|
||||
* object and persisted.
|
||||
|
@ -180,7 +174,7 @@ enum {
|
|||
|
||||
int write_object_file_flags(const void *buf, unsigned long len,
|
||||
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,
|
||||
enum object_type type, struct object_id *oid)
|
||||
{
|
||||
|
@ -193,9 +187,6 @@ struct input_stream {
|
|||
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,
|
||||
struct object_id *oid);
|
||||
|
||||
|
|
|
@ -646,8 +646,6 @@ static int do_oid_object_info_extended(struct repository *r,
|
|||
*(oi->disk_sizep) = 0;
|
||||
if (oi->delta_base_oid)
|
||||
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)
|
||||
*oi->contentp = xmemdupz(co->buf, co->size);
|
||||
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];
|
||||
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_info new_oi, *oi;
|
||||
unsigned long size;
|
||||
|
@ -753,7 +751,7 @@ static int oid_object_info_convert(struct repository *r,
|
|||
if (input_oi->sizep || input_oi->contentp) {
|
||||
new_oi.contentp = &content;
|
||||
new_oi.sizep = &size;
|
||||
new_oi.type_name = &type_name;
|
||||
new_oi.typep = &type;
|
||||
}
|
||||
oi = &new_oi;
|
||||
}
|
||||
|
@ -766,12 +764,7 @@ static int oid_object_info_convert(struct repository *r,
|
|||
|
||||
if (new_oi.contentp) {
|
||||
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) {
|
||||
ret = convert_object_file(the_repository, &outbuf,
|
||||
the_hash_algo, input_algo,
|
||||
|
@ -788,10 +781,8 @@ static int oid_object_info_convert(struct repository *r,
|
|||
*input_oi->contentp = content;
|
||||
else
|
||||
free(content);
|
||||
if (input_oi->type_name)
|
||||
*input_oi->type_name = type_name;
|
||||
else
|
||||
strbuf_release(&type_name);
|
||||
if (input_oi->typep)
|
||||
*input_oi->typep = type;
|
||||
}
|
||||
if (new_oi.delta_base_oid == &delta_base_oid) {
|
||||
if (repo_oid_to_algop(r, &delta_base_oid, input_algo,
|
||||
|
|
|
@ -206,7 +206,6 @@ struct object_info {
|
|||
unsigned long *sizep;
|
||||
off_t *disk_sizep;
|
||||
struct object_id *delta_base_oid;
|
||||
struct strbuf *type_name;
|
||||
void **contentp;
|
||||
|
||||
/* Response */
|
||||
|
@ -241,8 +240,6 @@ struct object_info {
|
|||
|
||||
/* Invoke lookup_replace_object() on the given hash */
|
||||
#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 */
|
||||
#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;
|
||||
}
|
||||
|
||||
if (oi->typep || oi->type_name) {
|
||||
if (oi->typep) {
|
||||
enum object_type ptot;
|
||||
ptot = packed_to_object_type(r, p, obj_offset,
|
||||
type, &w_curs, curpos);
|
||||
if (oi->typep)
|
||||
*oi->typep = ptot;
|
||||
if (oi->type_name) {
|
||||
const char *tn = type_name(ptot);
|
||||
if (tn)
|
||||
strbuf_addstr(oi->type_name, tn);
|
||||
}
|
||||
if (ptot < 0) {
|
||||
type = OBJ_BAD;
|
||||
goto out;
|
||||
|
|
|
@ -238,7 +238,7 @@ static int open_istream_loose(struct git_istream *st, struct repository *r,
|
|||
return -1;
|
||||
switch (unpack_loose_header(&st->z, st->u.loose.mapped,
|
||||
st->u.loose.mapsize, st->u.loose.hdr,
|
||||
sizeof(st->u.loose.hdr), NULL)) {
|
||||
sizeof(st->u.loose.hdr))) {
|
||||
case ULHR_OK:
|
||||
break;
|
||||
case ULHR_BAD:
|
||||
|
|
|
@ -77,6 +77,7 @@ test_tool_sources = [
|
|||
'test-windows-named-pipe.c',
|
||||
'test-write-cache.c',
|
||||
'test-xml-encode.c',
|
||||
'test-zlib.c',
|
||||
]
|
||||
|
||||
test_tool = executable('test-tool',
|
||||
|
|
|
@ -91,6 +91,7 @@ static struct test_cmd cmds[] = {
|
|||
{ "windows-named-pipe", cmd__windows_named_pipe },
|
||||
#endif
|
||||
{ "write-cache", cmd__write_cache },
|
||||
{ "zlib", cmd__zlib },
|
||||
};
|
||||
|
||||
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);
|
||||
#endif
|
||||
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);
|
||||
|
||||
|
|
|
@ -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-lib.sh
|
||||
. "$TEST_DIRECTORY/lib-loose.sh"
|
||||
|
||||
test_cmdmode_usage () {
|
||||
test_expect_code 129 "$@" 2>err &&
|
||||
|
@ -136,18 +137,6 @@ $content"
|
|||
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_expect_success "Content of $type is correct" '
|
||||
echo_without_newline "$content" >expect &&
|
||||
|
@ -669,103 +658,75 @@ test_expect_success 'setup bogus data' '
|
|||
bogus_short_type="bogus" &&
|
||||
bogus_short_content="bogus" &&
|
||||
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_content="bogus" &&
|
||||
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
|
||||
for arg2 in -s -t -p
|
||||
do
|
||||
if test "$arg1" = "--allow-unknown-type" && test "$arg2" = "-p"
|
||||
test_expect_success "cat-file $arg1 error on bogus short OID" '
|
||||
cat >expect <<-\EOF &&
|
||||
fatal: invalid object type
|
||||
EOF
|
||||
|
||||
test_must_fail git cat-file $arg1 $bogus_short_oid >out 2>actual &&
|
||||
test_must_be_empty out &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success "cat-file $arg1 error on bogus full OID" '
|
||||
if test "$arg1" = "-p"
|
||||
then
|
||||
continue
|
||||
fi
|
||||
|
||||
|
||||
test_expect_success "cat-file $arg1 $arg2 error on bogus short OID" '
|
||||
cat >expect <<-\EOF &&
|
||||
fatal: invalid object type
|
||||
cat >expect <<-EOF
|
||||
error: header for $bogus_long_oid too long, exceeds 32 bytes
|
||||
fatal: Not a valid object name $bogus_long_oid
|
||||
EOF
|
||||
|
||||
if test "$arg1" = "--allow-unknown-type"
|
||||
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_cmp expect actual
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success "cat-file $arg1 $arg2 error on bogus full OID" '
|
||||
if test "$arg2" = "-p"
|
||||
then
|
||||
cat >expect <<-EOF
|
||||
error: header for $bogus_long_oid too long, exceeds 32 bytes
|
||||
fatal: Not a valid object name $bogus_long_oid
|
||||
EOF
|
||||
else
|
||||
cat >expect <<-EOF
|
||||
error: header for $bogus_long_oid too long, exceeds 32 bytes
|
||||
fatal: git cat-file: could not get object info
|
||||
EOF
|
||||
fi &&
|
||||
|
||||
if test "$arg1" = "--allow-unknown-type"
|
||||
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_cmp expect actual
|
||||
fi
|
||||
'
|
||||
|
||||
test_expect_success "cat-file $arg1 $arg2 error on missing short OID" '
|
||||
cat >expect.err <<-EOF &&
|
||||
fatal: Not a valid object name $(test_oid deadbeef_short)
|
||||
else
|
||||
cat >expect <<-EOF
|
||||
error: header for $bogus_long_oid too long, exceeds 32 bytes
|
||||
fatal: git cat-file: could not get object info
|
||||
EOF
|
||||
test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef_short) >out 2>err.actual &&
|
||||
test_must_be_empty out &&
|
||||
test_cmp expect.err err.actual
|
||||
'
|
||||
fi &&
|
||||
|
||||
test_expect_success "cat-file $arg1 $arg2 error on missing full OID" '
|
||||
if test "$arg2" = "-p"
|
||||
then
|
||||
cat >expect.err <<-EOF
|
||||
fatal: Not a valid object name $(test_oid deadbeef)
|
||||
EOF
|
||||
else
|
||||
cat >expect.err <<-\EOF
|
||||
fatal: git cat-file: could not get object info
|
||||
EOF
|
||||
fi &&
|
||||
test_must_fail git cat-file $arg1 $arg2 $(test_oid deadbeef) >out 2>err.actual &&
|
||||
test_must_be_empty out &&
|
||||
test_cmp expect.err err.actual
|
||||
'
|
||||
done
|
||||
test_must_fail git cat-file $arg1 $bogus_long_oid >out 2>actual &&
|
||||
test_must_be_empty out &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success "cat-file $arg1 error on missing short OID" '
|
||||
cat >expect.err <<-EOF &&
|
||||
fatal: Not a valid object name $(test_oid deadbeef_short)
|
||||
EOF
|
||||
test_must_fail git cat-file $arg1 $(test_oid deadbeef_short) >out 2>err.actual &&
|
||||
test_must_be_empty out &&
|
||||
test_cmp expect.err err.actual
|
||||
'
|
||||
|
||||
test_expect_success "cat-file $arg1 error on missing full OID" '
|
||||
if test "$arg1" = "-p"
|
||||
then
|
||||
cat >expect.err <<-EOF
|
||||
fatal: Not a valid object name $(test_oid deadbeef)
|
||||
EOF
|
||||
else
|
||||
cat >expect.err <<-\EOF
|
||||
fatal: git cat-file: could not get object info
|
||||
EOF
|
||||
fi &&
|
||||
test_must_fail git cat-file $arg1 $(test_oid deadbeef) >out 2>err.actual &&
|
||||
test_must_be_empty out &&
|
||||
test_cmp expect.err err.actual
|
||||
'
|
||||
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
|
||||
'
|
||||
|
||||
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' '
|
||||
cat >err.expect <<-\EOF &&
|
||||
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_expect_success 'the --batch and --batch-check options do not combine with --allow-unknown-type' '
|
||||
test_expect_code 128 git cat-file --batch --allow-unknown-type <bogus-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' '
|
||||
test_expect_success 'clean up broken objects' '
|
||||
rm .git/objects/$(test_oid_to_path $bogus_short_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
|
||||
echo 'content that will be recompressed' >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_expect_success '--literally' '
|
||||
t=1234567890 &&
|
||||
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 '--literally complains about non-standard types' '
|
||||
test_must_fail git hash-object -t bogus --literally --stdin
|
||||
'
|
||||
|
||||
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_DIRECTORY/lib-loose.sh"
|
||||
|
||||
test_expect_success setup '
|
||||
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 ' '
|
||||
git init --bare corrupt-loose-output &&
|
||||
(
|
||||
|
@ -997,12 +974,13 @@ test_expect_success 'fsck error and recovery on invalid object 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 &&
|
||||
grep -e "^error" -e "^fatal" err >errors &&
|
||||
test_line_count = 1 errors &&
|
||||
grep "$garbage_blob: object is of unknown type '"'"'garbage'"'"':" err
|
||||
test_line_count = 2 errors &&
|
||||
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
|
||||
|
||||
. ./test-lib.sh
|
||||
. "$TEST_DIRECTORY/lib-loose.sh"
|
||||
|
||||
test_cmp_failed_rev_parse () {
|
||||
dir=$1
|
||||
|
@ -67,8 +68,8 @@ test_expect_success 'ambiguous loose bad object parsed as OBJ_BAD' '
|
|||
cd blob.bad &&
|
||||
|
||||
# Both have the prefix "bad0"
|
||||
echo xyzfaowcoh | git hash-object -t bad -w --stdin --literally &&
|
||||
echo xyzhjpyvwl | git hash-object -t bad -w --stdin --literally
|
||||
echo xyzfaowcoh | loose_obj objects bad &&
|
||||
echo xyzhjpyvwl | loose_obj objects bad
|
||||
) &&
|
||||
|
||||
test_cmp_failed_rev_parse blob.bad bad0 <<-\EOF
|
||||
|
|
Loading…
Reference in New Issue