Merge branch 'jt/rev-list-missing-print-info'
"git rev-list --missing=" learned to accept "print-info" that gives known details expected of the missing objects, like path and type. * jt/rev-list-missing-print-info: rev-list: extend print-info to print missing object type rev-list: add print-info action to print missing object pathmaint
commit
7722b997c6
|
@ -1024,6 +1024,25 @@ Unexpected missing objects will raise an error.
|
|||
The form '--missing=print' is like 'allow-any', but will also print a
|
||||
list of the missing objects. Object IDs are prefixed with a ``?'' character.
|
||||
+
|
||||
The form '--missing=print-info' is like 'print', but will also print additional
|
||||
information about the missing object inferred from its containing object. The
|
||||
information is all printed on the same line with the missing object ID in the
|
||||
form: `?<oid> [<token>=<value>]...`. The `<token>=<value>` pairs containing
|
||||
additional information are separated from each other by a SP. The value is
|
||||
encoded in a token specific fashion, but SP or LF contained in value are always
|
||||
expected to be represented in such a way that the resulting encoded value does
|
||||
not have either of these two problematic bytes. Each `<token>=<value>` may be
|
||||
one of the following:
|
||||
+
|
||||
--
|
||||
* The `path=<path>` shows the path of the missing object inferred from a
|
||||
containing object. A path containing SP or special characters is enclosed in
|
||||
double-quotes in the C style as needed.
|
||||
+
|
||||
* The `type=<type>` shows the type of the missing object inferred from a
|
||||
containing object.
|
||||
--
|
||||
+
|
||||
If some tips passed to the traversal are missing, they will be
|
||||
considered as missing too, and the traversal will ignore them. In case
|
||||
we cannot get their Object ID though, an error will be raised.
|
||||
|
|
|
@ -22,7 +22,10 @@
|
|||
#include "progress.h"
|
||||
#include "reflog-walk.h"
|
||||
#include "oidset.h"
|
||||
#include "oidmap.h"
|
||||
#include "packfile.h"
|
||||
#include "quote.h"
|
||||
#include "strbuf.h"
|
||||
|
||||
static const char rev_list_usage[] =
|
||||
"git rev-list [<options>] <commit>... [--] [<path>...]\n"
|
||||
|
@ -73,11 +76,17 @@ static unsigned progress_counter;
|
|||
static struct oidset omitted_objects;
|
||||
static int arg_print_omitted; /* print objects omitted by filter */
|
||||
|
||||
static struct oidset missing_objects;
|
||||
struct missing_objects_map_entry {
|
||||
struct oidmap_entry entry;
|
||||
const char *path;
|
||||
unsigned type;
|
||||
};
|
||||
static struct oidmap missing_objects;
|
||||
enum missing_action {
|
||||
MA_ERROR = 0, /* fail if any missing objects are encountered */
|
||||
MA_ALLOW_ANY, /* silently allow ALL missing objects */
|
||||
MA_PRINT, /* print ALL missing objects in special section */
|
||||
MA_PRINT_INFO, /* same as MA_PRINT but also prints missing object info */
|
||||
MA_ALLOW_PROMISOR, /* silently allow all missing PROMISOR objects */
|
||||
};
|
||||
static enum missing_action arg_missing_action;
|
||||
|
@ -101,7 +110,49 @@ static off_t get_object_disk_usage(struct object *obj)
|
|||
return size;
|
||||
}
|
||||
|
||||
static inline void finish_object__ma(struct object *obj)
|
||||
static void add_missing_object_entry(struct object_id *oid, const char *path,
|
||||
unsigned type)
|
||||
{
|
||||
struct missing_objects_map_entry *entry;
|
||||
|
||||
if (oidmap_get(&missing_objects, oid))
|
||||
return;
|
||||
|
||||
CALLOC_ARRAY(entry, 1);
|
||||
entry->entry.oid = *oid;
|
||||
entry->type = type;
|
||||
if (path)
|
||||
entry->path = xstrdup(path);
|
||||
oidmap_put(&missing_objects, entry);
|
||||
}
|
||||
|
||||
static void print_missing_object(struct missing_objects_map_entry *entry,
|
||||
int print_missing_info)
|
||||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
if (!print_missing_info) {
|
||||
printf("?%s\n", oid_to_hex(&entry->entry.oid));
|
||||
return;
|
||||
}
|
||||
|
||||
if (entry->path && *entry->path) {
|
||||
struct strbuf path = STRBUF_INIT;
|
||||
|
||||
strbuf_addstr(&sb, " path=");
|
||||
quote_path(entry->path, NULL, &path, QUOTE_PATH_QUOTE_SP);
|
||||
strbuf_addbuf(&sb, &path);
|
||||
|
||||
strbuf_release(&path);
|
||||
}
|
||||
if (entry->type)
|
||||
strbuf_addf(&sb, " type=%s", type_name(entry->type));
|
||||
|
||||
printf("?%s%s\n", oid_to_hex(&entry->entry.oid), sb.buf);
|
||||
strbuf_release(&sb);
|
||||
}
|
||||
|
||||
static inline void finish_object__ma(struct object *obj, const char *name)
|
||||
{
|
||||
/*
|
||||
* Whether or not we try to dynamically fetch missing objects
|
||||
|
@ -119,7 +170,8 @@ static inline void finish_object__ma(struct object *obj)
|
|||
return;
|
||||
|
||||
case MA_PRINT:
|
||||
oidset_insert(&missing_objects, &obj->oid);
|
||||
case MA_PRINT_INFO:
|
||||
add_missing_object_entry(&obj->oid, name, obj->type);
|
||||
return;
|
||||
|
||||
case MA_ALLOW_PROMISOR:
|
||||
|
@ -152,7 +204,7 @@ static void show_commit(struct commit *commit, void *data)
|
|||
|
||||
if (revs->do_not_die_on_missing_objects &&
|
||||
oidset_contains(&revs->missing_commits, &commit->object.oid)) {
|
||||
finish_object__ma(&commit->object);
|
||||
finish_object__ma(&commit->object, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -268,12 +320,11 @@ static void show_commit(struct commit *commit, void *data)
|
|||
finish_commit(commit);
|
||||
}
|
||||
|
||||
static int finish_object(struct object *obj, const char *name UNUSED,
|
||||
void *cb_data)
|
||||
static int finish_object(struct object *obj, const char *name, void *cb_data)
|
||||
{
|
||||
struct rev_list_info *info = cb_data;
|
||||
if (oid_object_info_extended(the_repository, &obj->oid, NULL, 0) < 0) {
|
||||
finish_object__ma(obj);
|
||||
finish_object__ma(obj, name);
|
||||
return 1;
|
||||
}
|
||||
if (info->revs->verify_objects && !obj->parsed && obj->type != OBJ_COMMIT)
|
||||
|
@ -414,6 +465,12 @@ static inline int parse_missing_action_value(const char *value)
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(value, "print-info")) {
|
||||
arg_missing_action = MA_PRINT_INFO;
|
||||
fetch_if_missing = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strcmp(value, "allow-promisor")) {
|
||||
arg_missing_action = MA_ALLOW_PROMISOR;
|
||||
fetch_if_missing = 0;
|
||||
|
@ -781,10 +838,18 @@ int cmd_rev_list(int argc,
|
|||
|
||||
if (arg_print_omitted)
|
||||
oidset_init(&omitted_objects, DEFAULT_OIDSET_SIZE);
|
||||
if (arg_missing_action == MA_PRINT) {
|
||||
oidset_init(&missing_objects, DEFAULT_OIDSET_SIZE);
|
||||
if (arg_missing_action == MA_PRINT ||
|
||||
arg_missing_action == MA_PRINT_INFO) {
|
||||
struct oidset_iter iter;
|
||||
struct object_id *oid;
|
||||
|
||||
oidmap_init(&missing_objects, DEFAULT_OIDSET_SIZE);
|
||||
oidset_iter_init(&revs.missing_commits, &iter);
|
||||
|
||||
/* Add missing tips */
|
||||
oidset_insert_from_set(&missing_objects, &revs.missing_commits);
|
||||
while ((oid = oidset_iter_next(&iter)))
|
||||
add_missing_object_entry(oid, NULL, 0);
|
||||
|
||||
oidset_clear(&revs.missing_commits);
|
||||
}
|
||||
|
||||
|
@ -800,13 +865,20 @@ int cmd_rev_list(int argc,
|
|||
printf("~%s\n", oid_to_hex(oid));
|
||||
oidset_clear(&omitted_objects);
|
||||
}
|
||||
if (arg_missing_action == MA_PRINT) {
|
||||
struct oidset_iter iter;
|
||||
struct object_id *oid;
|
||||
oidset_iter_init(&missing_objects, &iter);
|
||||
while ((oid = oidset_iter_next(&iter)))
|
||||
printf("?%s\n", oid_to_hex(oid));
|
||||
oidset_clear(&missing_objects);
|
||||
if (arg_missing_action == MA_PRINT ||
|
||||
arg_missing_action == MA_PRINT_INFO) {
|
||||
struct missing_objects_map_entry *entry;
|
||||
struct oidmap_iter iter;
|
||||
|
||||
oidmap_iter_init(&missing_objects, &iter);
|
||||
|
||||
while ((entry = oidmap_iter_next(&iter))) {
|
||||
print_missing_object(entry, arg_missing_action ==
|
||||
MA_PRINT_INFO);
|
||||
free((void *)entry->path);
|
||||
}
|
||||
|
||||
oidmap_free(&missing_objects, true);
|
||||
}
|
||||
|
||||
stop_progress(&progress);
|
||||
|
|
|
@ -145,4 +145,57 @@ do
|
|||
done
|
||||
done
|
||||
|
||||
for obj in "HEAD~1" "HEAD^{tree}" "HEAD:foo" "HEAD:foo/bar" "HEAD:baz baz"
|
||||
do
|
||||
test_expect_success "--missing=print-info with missing '$obj'" '
|
||||
test_when_finished rm -rf missing-info &&
|
||||
|
||||
git init missing-info &&
|
||||
(
|
||||
cd missing-info &&
|
||||
git commit --allow-empty -m first &&
|
||||
|
||||
mkdir foo &&
|
||||
echo bar >foo/bar &&
|
||||
echo baz >"baz baz" &&
|
||||
echo bat >bat\" &&
|
||||
git add -A &&
|
||||
git commit -m second &&
|
||||
|
||||
oid="$(git rev-parse "$obj")" &&
|
||||
path=".git/objects/$(test_oid_to_path $oid)" &&
|
||||
type_info=" type=$(git cat-file -t $oid)" &&
|
||||
|
||||
case $obj in
|
||||
HEAD:foo)
|
||||
path_info=" path=foo"
|
||||
;;
|
||||
HEAD:foo/bar)
|
||||
path_info=" path=foo/bar"
|
||||
;;
|
||||
"HEAD:baz baz")
|
||||
path_info=" path=\"baz baz\""
|
||||
;;
|
||||
"HEAD:bat\"")
|
||||
path_info=" path=\"bat\\\"\""
|
||||
;;
|
||||
esac &&
|
||||
|
||||
# Before the object is made missing, we use rev-list to
|
||||
# get the expected oids.
|
||||
git rev-list --objects --no-object-names \
|
||||
HEAD ^"$obj" >expect.raw &&
|
||||
echo "?$oid$path_info$type_info" >>expect.raw &&
|
||||
|
||||
mv "$path" "$path.hidden" &&
|
||||
git rev-list --objects --no-object-names \
|
||||
--missing=print-info HEAD >actual.raw &&
|
||||
|
||||
sort actual.raw >actual &&
|
||||
sort expect.raw >expect &&
|
||||
test_cmp expect actual
|
||||
)
|
||||
'
|
||||
done
|
||||
|
||||
test_done
|
||||
|
|
Loading…
Reference in New Issue