зеркало из https://github.com/microsoft/git.git
Merge branch 'nd/commit-util-to-slab'
The in-core "commit" object had an all-purpose "void *util" field, which was tricky to use especially in library-ish part of the code. All of the existing uses of the field has been migrated to a more dedicated "commit-slab" mechanism and the field is eliminated. * nd/commit-util-to-slab: commit.h: delete 'util' field in struct commit merge: use commit-slab in merge remote desc instead of commit->util log: use commit-slab in prepare_bases() instead of commit->util show-branch: note about its object flags usage show-branch: use commit-slab for commit-name instead of commit->util name-rev: use commit-slab for rev-name instead of commit->util bisect.c: use commit-slab for commit weight instead of commit->util revision.c: use commit-slab for show_source sequencer.c: use commit-slab to associate todo items to commits sequencer.c: use commit-slab to mark seen commits shallow.c: use commit-slab for commit depth instead of commit->util describe: use commit-slab for commit names instead of commit->util blame: use commit-slab for blame suspects instead of commit->util commit-slab: support shared commit-slab commit-slab.h: code split
This commit is contained in:
Коммит
b3b2aaf0fd
12
bisect.c
12
bisect.c
|
@ -12,6 +12,7 @@
|
|||
#include "bisect.h"
|
||||
#include "sha1-array.h"
|
||||
#include "argv-array.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
static struct oid_array good_revs;
|
||||
static struct oid_array skipped_revs;
|
||||
|
@ -70,16 +71,19 @@ static void clear_distance(struct commit_list *list)
|
|||
}
|
||||
}
|
||||
|
||||
define_commit_slab(commit_weight, int *);
|
||||
static struct commit_weight commit_weight;
|
||||
|
||||
#define DEBUG_BISECT 0
|
||||
|
||||
static inline int weight(struct commit_list *elem)
|
||||
{
|
||||
return *((int*)(elem->item->util));
|
||||
return **commit_weight_at(&commit_weight, elem->item);
|
||||
}
|
||||
|
||||
static inline void weight_set(struct commit_list *elem, int weight)
|
||||
{
|
||||
*((int*)(elem->item->util)) = weight;
|
||||
**commit_weight_at(&commit_weight, elem->item) = weight;
|
||||
}
|
||||
|
||||
static int count_interesting_parents(struct commit *commit)
|
||||
|
@ -265,7 +269,7 @@ static struct commit_list *do_find_bisection(struct commit_list *list,
|
|||
struct commit *commit = p->item;
|
||||
unsigned flags = commit->object.flags;
|
||||
|
||||
p->item->util = &weights[n++];
|
||||
*commit_weight_at(&commit_weight, p->item) = &weights[n++];
|
||||
switch (count_interesting_parents(commit)) {
|
||||
case 0:
|
||||
if (!(flags & TREESAME)) {
|
||||
|
@ -372,6 +376,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
|
|||
int *weights;
|
||||
|
||||
show_list("bisection 2 entry", 0, 0, *commit_list);
|
||||
init_commit_weight(&commit_weight);
|
||||
|
||||
/*
|
||||
* Count the number of total and tree-changing items on the
|
||||
|
@ -412,6 +417,7 @@ void find_bisection(struct commit_list **commit_list, int *reaches,
|
|||
}
|
||||
free(weights);
|
||||
*commit_list = best;
|
||||
clear_commit_weight(&commit_weight);
|
||||
}
|
||||
|
||||
static int register_ref(const char *refname, const struct object_id *oid,
|
||||
|
|
42
blame.c
42
blame.c
|
@ -6,6 +6,24 @@
|
|||
#include "diffcore.h"
|
||||
#include "tag.h"
|
||||
#include "blame.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
define_commit_slab(blame_suspects, struct blame_origin *);
|
||||
static struct blame_suspects blame_suspects;
|
||||
|
||||
struct blame_origin *get_blame_suspects(struct commit *commit)
|
||||
{
|
||||
struct blame_origin **result;
|
||||
|
||||
result = blame_suspects_peek(&blame_suspects, commit);
|
||||
|
||||
return result ? *result : NULL;
|
||||
}
|
||||
|
||||
static void set_blame_suspects(struct commit *commit, struct blame_origin *origin)
|
||||
{
|
||||
*blame_suspects_at(&blame_suspects, commit) = origin;
|
||||
}
|
||||
|
||||
void blame_origin_decref(struct blame_origin *o)
|
||||
{
|
||||
|
@ -15,12 +33,12 @@ void blame_origin_decref(struct blame_origin *o)
|
|||
blame_origin_decref(o->previous);
|
||||
free(o->file.ptr);
|
||||
/* Should be present exactly once in commit chain */
|
||||
for (p = o->commit->util; p; l = p, p = p->next) {
|
||||
for (p = get_blame_suspects(o->commit); p; l = p, p = p->next) {
|
||||
if (p == o) {
|
||||
if (l)
|
||||
l->next = p->next;
|
||||
else
|
||||
o->commit->util = p->next;
|
||||
set_blame_suspects(o->commit, p->next);
|
||||
free(o);
|
||||
return;
|
||||
}
|
||||
|
@ -41,8 +59,8 @@ static struct blame_origin *make_origin(struct commit *commit, const char *path)
|
|||
FLEX_ALLOC_STR(o, path, path);
|
||||
o->commit = commit;
|
||||
o->refcnt = 1;
|
||||
o->next = commit->util;
|
||||
commit->util = o;
|
||||
o->next = get_blame_suspects(commit);
|
||||
set_blame_suspects(commit, o);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
@ -54,13 +72,13 @@ static struct blame_origin *get_origin(struct commit *commit, const char *path)
|
|||
{
|
||||
struct blame_origin *o, *l;
|
||||
|
||||
for (o = commit->util, l = NULL; o; l = o, o = o->next) {
|
||||
for (o = get_blame_suspects(commit), l = NULL; o; l = o, o = o->next) {
|
||||
if (!strcmp(o->path, path)) {
|
||||
/* bump to front */
|
||||
if (l) {
|
||||
l->next = o->next;
|
||||
o->next = commit->util;
|
||||
commit->util = o;
|
||||
o->next = get_blame_suspects(commit);
|
||||
set_blame_suspects(commit, o);
|
||||
}
|
||||
return blame_origin_incref(o);
|
||||
}
|
||||
|
@ -478,7 +496,7 @@ static void queue_blames(struct blame_scoreboard *sb, struct blame_origin *porig
|
|||
porigin->suspects = blame_merge(porigin->suspects, sorted);
|
||||
else {
|
||||
struct blame_origin *o;
|
||||
for (o = porigin->commit->util; o; o = o->next) {
|
||||
for (o = get_blame_suspects(porigin->commit); o; o = o->next) {
|
||||
if (o->suspects) {
|
||||
porigin->suspects = sorted;
|
||||
return;
|
||||
|
@ -525,7 +543,7 @@ static struct blame_origin *find_origin(struct commit *parent,
|
|||
const char *paths[2];
|
||||
|
||||
/* First check any existing origins */
|
||||
for (porigin = parent->util; porigin; porigin = porigin->next)
|
||||
for (porigin = get_blame_suspects(parent); porigin; porigin = porigin->next)
|
||||
if (!strcmp(porigin->path, origin->path)) {
|
||||
/*
|
||||
* The same path between origin and its parent
|
||||
|
@ -1550,7 +1568,7 @@ void assign_blame(struct blame_scoreboard *sb, int opt)
|
|||
|
||||
while (commit) {
|
||||
struct blame_entry *ent;
|
||||
struct blame_origin *suspect = commit->util;
|
||||
struct blame_origin *suspect = get_blame_suspects(commit);
|
||||
|
||||
/* find one suspect to break down */
|
||||
while (suspect && !suspect->suspects)
|
||||
|
@ -1752,6 +1770,8 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
|
|||
struct commit *final_commit = NULL;
|
||||
enum object_type type;
|
||||
|
||||
init_blame_suspects(&blame_suspects);
|
||||
|
||||
if (sb->reverse && sb->contents_from)
|
||||
die(_("--contents and --reverse do not blend well."));
|
||||
|
||||
|
@ -1815,7 +1835,7 @@ void setup_scoreboard(struct blame_scoreboard *sb, const char *path, struct blam
|
|||
}
|
||||
|
||||
if (is_null_oid(&sb->final->object.oid)) {
|
||||
o = sb->final->util;
|
||||
o = get_blame_suspects(sb->final);
|
||||
sb->final_buf = xmemdupz(o->file.ptr, o->file.size);
|
||||
sb->final_buf_size = o->file.size;
|
||||
}
|
||||
|
|
2
blame.h
2
blame.h
|
@ -172,4 +172,6 @@ extern void setup_scoreboard(struct blame_scoreboard *sb, const char *path, stru
|
|||
|
||||
extern struct blame_entry *blame_entry_prepend(struct blame_entry *head, long start, long end, struct blame_origin *o);
|
||||
|
||||
extern struct blame_origin *get_blame_suspects(struct commit *commit);
|
||||
|
||||
#endif /* BLAME_H */
|
||||
|
|
|
@ -543,7 +543,7 @@ static void output(struct blame_scoreboard *sb, int option)
|
|||
struct commit *commit = ent->suspect->commit;
|
||||
if (commit->object.flags & MORE_THAN_ONE_PATH)
|
||||
continue;
|
||||
for (suspect = commit->util; suspect; suspect = suspect->next) {
|
||||
for (suspect = get_blame_suspects(commit); suspect; suspect = suspect->next) {
|
||||
if (suspect->guilty && count++) {
|
||||
commit->object.flags |= MORE_THAN_ONE_PATH;
|
||||
break;
|
||||
|
|
|
@ -15,9 +15,12 @@
|
|||
#include "run-command.h"
|
||||
#include "revision.h"
|
||||
#include "list-objects.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
#define MAX_TAGS (FLAG_BITS - 1)
|
||||
|
||||
define_commit_slab(commit_names, struct commit_name *);
|
||||
|
||||
static const char * const describe_usage[] = {
|
||||
N_("git describe [<options>] [<commit-ish>...]"),
|
||||
N_("git describe [<options>] --dirty"),
|
||||
|
@ -37,6 +40,7 @@ static struct string_list patterns = STRING_LIST_INIT_NODUP;
|
|||
static struct string_list exclude_patterns = STRING_LIST_INIT_NODUP;
|
||||
static int always;
|
||||
static const char *suffix, *dirty, *broken;
|
||||
static struct commit_names commit_names;
|
||||
|
||||
/* diff-index command arguments to check if working tree is dirty. */
|
||||
static const char *diff_index_args[] = {
|
||||
|
@ -321,11 +325,14 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
|
|||
if (!have_util) {
|
||||
struct hashmap_iter iter;
|
||||
struct commit *c;
|
||||
struct commit_name *n = hashmap_iter_first(&names, &iter);
|
||||
struct commit_name *n;
|
||||
|
||||
init_commit_names(&commit_names);
|
||||
n = hashmap_iter_first(&names, &iter);
|
||||
for (; n; n = hashmap_iter_next(&iter)) {
|
||||
c = lookup_commit_reference_gently(&n->peeled, 1);
|
||||
if (c)
|
||||
c->util = n;
|
||||
*commit_names_at(&commit_names, c) = n;
|
||||
}
|
||||
have_util = 1;
|
||||
}
|
||||
|
@ -336,8 +343,11 @@ static void describe_commit(struct object_id *oid, struct strbuf *dst)
|
|||
while (list) {
|
||||
struct commit *c = pop_commit(&list);
|
||||
struct commit_list *parents = c->parents;
|
||||
struct commit_name **slot;
|
||||
|
||||
seen_commits++;
|
||||
n = c->util;
|
||||
slot = commit_names_peek(&commit_names, c);
|
||||
n = slot ? *slot : NULL;
|
||||
if (n) {
|
||||
if (!tags && !all && n->prio < 2) {
|
||||
unannotated_cnt++;
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "quote.h"
|
||||
#include "remote.h"
|
||||
#include "blob.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
static const char *fast_export_usage[] = {
|
||||
N_("git fast-export [rev-list-opts]"),
|
||||
|
@ -38,6 +39,7 @@ static int full_tree;
|
|||
static struct string_list extra_refs = STRING_LIST_INIT_NODUP;
|
||||
static struct refspec refspecs = REFSPEC_INIT_FETCH;
|
||||
static int anonymize;
|
||||
static struct revision_sources revision_sources;
|
||||
|
||||
static int parse_opt_signed_tag_mode(const struct option *opt,
|
||||
const char *arg, int unset)
|
||||
|
@ -589,7 +591,7 @@ static void handle_commit(struct commit *commit, struct rev_info *rev,
|
|||
if (!S_ISGITLINK(diff_queued_diff.queue[i]->two->mode))
|
||||
export_blob(&diff_queued_diff.queue[i]->two->oid);
|
||||
|
||||
refname = commit->util;
|
||||
refname = *revision_sources_at(&revision_sources, commit);
|
||||
if (anonymize) {
|
||||
refname = anonymize_refname(refname);
|
||||
anonymize_ident_line(&committer, &committer_end);
|
||||
|
@ -861,10 +863,11 @@ static void get_tags_and_duplicates(struct rev_cmdline_info *info)
|
|||
* This ref will not be updated through a commit, lets make
|
||||
* sure it gets properly updated eventually.
|
||||
*/
|
||||
if (commit->util || commit->object.flags & SHOWN)
|
||||
if (*revision_sources_at(&revision_sources, commit) ||
|
||||
commit->object.flags & SHOWN)
|
||||
string_list_append(&extra_refs, full_name)->util = commit;
|
||||
if (!commit->util)
|
||||
commit->util = full_name;
|
||||
if (!*revision_sources_at(&revision_sources, commit))
|
||||
*revision_sources_at(&revision_sources, commit) = full_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1028,8 +1031,9 @@ int cmd_fast_export(int argc, const char **argv, const char *prefix)
|
|||
git_config(git_default_config, NULL);
|
||||
|
||||
init_revisions(&revs, prefix);
|
||||
init_revision_sources(&revision_sources);
|
||||
revs.topo_order = 1;
|
||||
revs.show_source = 1;
|
||||
revs.sources = &revision_sources;
|
||||
revs.rewrite_parents = 1;
|
||||
argc = parse_options(argc, argv, prefix, options, fast_export_usage,
|
||||
PARSE_OPT_KEEP_ARGV0 | PARSE_OPT_KEEP_UNKNOWN);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "mailmap.h"
|
||||
#include "gpg-interface.h"
|
||||
#include "progress.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
#define MAIL_DEFAULT_WRAP 72
|
||||
|
||||
|
@ -148,6 +149,7 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
|
|||
static struct string_list decorate_refs_include = STRING_LIST_INIT_NODUP;
|
||||
struct decoration_filter decoration_filter = {&decorate_refs_include,
|
||||
&decorate_refs_exclude};
|
||||
static struct revision_sources revision_sources;
|
||||
|
||||
const struct option builtin_log_options[] = {
|
||||
OPT__QUIET(&quiet, N_("suppress diff output")),
|
||||
|
@ -194,8 +196,10 @@ static void cmd_log_init_finish(int argc, const char **argv, const char *prefix,
|
|||
rev->diffopt.filter || rev->diffopt.flags.follow_renames)
|
||||
rev->always_show_header = 0;
|
||||
|
||||
if (source)
|
||||
rev->show_source = 1;
|
||||
if (source) {
|
||||
init_revision_sources(&revision_sources);
|
||||
rev->sources = &revision_sources;
|
||||
}
|
||||
|
||||
if (mailmap) {
|
||||
rev->mailmap = xcalloc(1, sizeof(struct string_list));
|
||||
|
@ -1337,6 +1341,8 @@ static struct commit *get_base_commit(const char *base_commit,
|
|||
return base;
|
||||
}
|
||||
|
||||
define_commit_slab(commit_base, int);
|
||||
|
||||
static void prepare_bases(struct base_tree_info *bases,
|
||||
struct commit *base,
|
||||
struct commit **list,
|
||||
|
@ -1345,11 +1351,13 @@ static void prepare_bases(struct base_tree_info *bases,
|
|||
struct commit *commit;
|
||||
struct rev_info revs;
|
||||
struct diff_options diffopt;
|
||||
struct commit_base commit_base;
|
||||
int i;
|
||||
|
||||
if (!base)
|
||||
return;
|
||||
|
||||
init_commit_base(&commit_base);
|
||||
diff_setup(&diffopt);
|
||||
diffopt.flags.recursive = 1;
|
||||
diff_setup_done(&diffopt);
|
||||
|
@ -1362,7 +1370,7 @@ static void prepare_bases(struct base_tree_info *bases,
|
|||
for (i = 0; i < total; i++) {
|
||||
list[i]->object.flags &= ~UNINTERESTING;
|
||||
add_pending_object(&revs, &list[i]->object, "rev_list");
|
||||
list[i]->util = (void *)1;
|
||||
*commit_base_at(&commit_base, list[i]) = 1;
|
||||
}
|
||||
base->object.flags |= UNINTERESTING;
|
||||
add_pending_object(&revs, &base->object, "base");
|
||||
|
@ -1376,7 +1384,7 @@ static void prepare_bases(struct base_tree_info *bases,
|
|||
while ((commit = get_revision(&revs)) != NULL) {
|
||||
struct object_id oid;
|
||||
struct object_id *patch_id;
|
||||
if (commit->util)
|
||||
if (*commit_base_at(&commit_base, commit))
|
||||
continue;
|
||||
if (commit_patch_id(commit, &diffopt, &oid, 0))
|
||||
die(_("cannot get patch id"));
|
||||
|
@ -1385,6 +1393,7 @@ static void prepare_bases(struct base_tree_info *bases,
|
|||
oidcpy(patch_id, &oid);
|
||||
bases->nr_patch_id++;
|
||||
}
|
||||
clear_commit_base(&commit_base);
|
||||
}
|
||||
|
||||
static void print_bases(struct base_tree_info *bases, FILE *file)
|
||||
|
|
|
@ -445,6 +445,7 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
|||
struct object_id branch_head;
|
||||
struct strbuf buf = STRBUF_INIT;
|
||||
struct strbuf bname = STRBUF_INIT;
|
||||
struct merge_remote_desc *desc;
|
||||
const char *ptr;
|
||||
char *found_ref;
|
||||
int len, early;
|
||||
|
@ -517,8 +518,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
|||
strbuf_release(&truname);
|
||||
}
|
||||
|
||||
if (remote_head->util) {
|
||||
struct merge_remote_desc *desc;
|
||||
desc = merge_remote_util(remote_head);
|
||||
if (desc && desc->obj && desc->obj->type == OBJ_TAG) {
|
||||
strbuf_addf(msg, "%s\t\t%s '%s'\n",
|
||||
|
@ -527,7 +526,6 @@ static void merge_name(const char *remote, struct strbuf *msg)
|
|||
remote);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
strbuf_addf(msg, "%s\t\tcommit '%s'\n",
|
||||
oid_to_hex(&remote_head->object.oid), remote);
|
||||
|
@ -934,8 +932,11 @@ static void write_merge_heads(struct commit_list *remoteheads)
|
|||
for (j = remoteheads; j; j = j->next) {
|
||||
struct object_id *oid;
|
||||
struct commit *c = j->item;
|
||||
if (c->util && merge_remote_util(c)->obj) {
|
||||
oid = &merge_remote_util(c)->obj->oid;
|
||||
struct merge_remote_desc *desc;
|
||||
|
||||
desc = merge_remote_util(c);
|
||||
if (desc && desc->obj) {
|
||||
oid = &desc->obj->oid;
|
||||
} else {
|
||||
oid = &c->object.oid;
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "refs.h"
|
||||
#include "parse-options.h"
|
||||
#include "sha1-lookup.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
#define CUTOFF_DATE_SLOP 86400 /* one day */
|
||||
|
||||
|
@ -17,11 +18,26 @@ typedef struct rev_name {
|
|||
int from_tag;
|
||||
} rev_name;
|
||||
|
||||
define_commit_slab(commit_rev_name, struct rev_name *);
|
||||
|
||||
static timestamp_t cutoff = TIME_MAX;
|
||||
static struct commit_rev_name rev_names;
|
||||
|
||||
/* How many generations are maximally preferred over _one_ merge traversal? */
|
||||
#define MERGE_TRAVERSAL_WEIGHT 65535
|
||||
|
||||
static struct rev_name *get_commit_rev_name(struct commit *commit)
|
||||
{
|
||||
struct rev_name **slot = commit_rev_name_peek(&rev_names, commit);
|
||||
|
||||
return slot ? *slot : NULL;
|
||||
}
|
||||
|
||||
static void set_commit_rev_name(struct commit *commit, struct rev_name *name)
|
||||
{
|
||||
*commit_rev_name_at(&rev_names, commit) = name;
|
||||
}
|
||||
|
||||
static int is_better_name(struct rev_name *name,
|
||||
const char *tip_name,
|
||||
timestamp_t taggerdate,
|
||||
|
@ -65,7 +81,7 @@ static void name_rev(struct commit *commit,
|
|||
int generation, int distance, int from_tag,
|
||||
int deref)
|
||||
{
|
||||
struct rev_name *name = (struct rev_name *)commit->util;
|
||||
struct rev_name *name = get_commit_rev_name(commit);
|
||||
struct commit_list *parents;
|
||||
int parent_number = 1;
|
||||
char *to_free = NULL;
|
||||
|
@ -84,7 +100,7 @@ static void name_rev(struct commit *commit,
|
|||
|
||||
if (name == NULL) {
|
||||
name = xmalloc(sizeof(rev_name));
|
||||
commit->util = name;
|
||||
set_commit_rev_name(commit, name);
|
||||
goto copy_data;
|
||||
} else if (is_better_name(name, tip_name, taggerdate,
|
||||
generation, distance, from_tag)) {
|
||||
|
@ -296,7 +312,7 @@ static const char *get_rev_name(const struct object *o, struct strbuf *buf)
|
|||
if (o->type != OBJ_COMMIT)
|
||||
return get_exact_ref_match(o);
|
||||
c = (struct commit *) o;
|
||||
n = c->util;
|
||||
n = get_commit_rev_name(c);
|
||||
if (!n)
|
||||
return NULL;
|
||||
|
||||
|
@ -413,6 +429,7 @@ int cmd_name_rev(int argc, const char **argv, const char *prefix)
|
|||
OPT_END(),
|
||||
};
|
||||
|
||||
init_commit_rev_name(&rev_names);
|
||||
git_config(git_default_config, NULL);
|
||||
argc = parse_options(argc, argv, prefix, opts, name_rev_usage, 0);
|
||||
if (all + transform_stdin + !!argc > 1) {
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
#include "argv-array.h"
|
||||
#include "parse-options.h"
|
||||
#include "dir.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
static const char* show_branch_usage[] = {
|
||||
N_("git show-branch [-a | --all] [-r | --remotes] [--topo-order | --date-order]\n"
|
||||
|
@ -21,6 +22,11 @@ static int showbranch_use_color = -1;
|
|||
|
||||
static struct argv_array default_args = ARGV_ARRAY_INIT;
|
||||
|
||||
/*
|
||||
* TODO: convert this use of commit->object.flags to commit-slab
|
||||
* instead to store a pointer to ref name directly. Then use the same
|
||||
* UNINTERESTING definition from revision.h here.
|
||||
*/
|
||||
#define UNINTERESTING 01
|
||||
|
||||
#define REV_SHIFT 2
|
||||
|
@ -59,15 +65,27 @@ struct commit_name {
|
|||
int generation; /* how many parents away from head_name */
|
||||
};
|
||||
|
||||
define_commit_slab(commit_name_slab, struct commit_name *);
|
||||
static struct commit_name_slab name_slab;
|
||||
|
||||
static struct commit_name *commit_to_name(struct commit *commit)
|
||||
{
|
||||
return *commit_name_slab_at(&name_slab, commit);
|
||||
}
|
||||
|
||||
|
||||
/* Name the commit as nth generation ancestor of head_name;
|
||||
* we count only the first-parent relationship for naming purposes.
|
||||
*/
|
||||
static void name_commit(struct commit *commit, const char *head_name, int nth)
|
||||
{
|
||||
struct commit_name *name;
|
||||
if (!commit->util)
|
||||
commit->util = xmalloc(sizeof(struct commit_name));
|
||||
name = commit->util;
|
||||
|
||||
name = *commit_name_slab_at(&name_slab, commit);
|
||||
if (!name) {
|
||||
name = xmalloc(sizeof(*name));
|
||||
*commit_name_slab_at(&name_slab, commit) = name;
|
||||
}
|
||||
name->head_name = head_name;
|
||||
name->generation = nth;
|
||||
}
|
||||
|
@ -79,8 +97,8 @@ static void name_commit(struct commit *commit, const char *head_name, int nth)
|
|||
*/
|
||||
static void name_parent(struct commit *commit, struct commit *parent)
|
||||
{
|
||||
struct commit_name *commit_name = commit->util;
|
||||
struct commit_name *parent_name = parent->util;
|
||||
struct commit_name *commit_name = commit_to_name(commit);
|
||||
struct commit_name *parent_name = commit_to_name(parent);
|
||||
if (!commit_name)
|
||||
return;
|
||||
if (!parent_name ||
|
||||
|
@ -94,12 +112,12 @@ static int name_first_parent_chain(struct commit *c)
|
|||
int i = 0;
|
||||
while (c) {
|
||||
struct commit *p;
|
||||
if (!c->util)
|
||||
if (!commit_to_name(c))
|
||||
break;
|
||||
if (!c->parents)
|
||||
break;
|
||||
p = c->parents->item;
|
||||
if (!p->util) {
|
||||
if (!commit_to_name(p)) {
|
||||
name_parent(c, p);
|
||||
i++;
|
||||
}
|
||||
|
@ -122,7 +140,7 @@ static void name_commits(struct commit_list *list,
|
|||
/* First give names to the given heads */
|
||||
for (cl = list; cl; cl = cl->next) {
|
||||
c = cl->item;
|
||||
if (c->util)
|
||||
if (commit_to_name(c))
|
||||
continue;
|
||||
for (i = 0; i < num_rev; i++) {
|
||||
if (rev[i] == c) {
|
||||
|
@ -148,9 +166,9 @@ static void name_commits(struct commit_list *list,
|
|||
struct commit_name *n;
|
||||
int nth;
|
||||
c = cl->item;
|
||||
if (!c->util)
|
||||
if (!commit_to_name(c))
|
||||
continue;
|
||||
n = c->util;
|
||||
n = commit_to_name(c);
|
||||
parents = c->parents;
|
||||
nth = 0;
|
||||
while (parents) {
|
||||
|
@ -158,7 +176,7 @@ static void name_commits(struct commit_list *list,
|
|||
struct strbuf newname = STRBUF_INIT;
|
||||
parents = parents->next;
|
||||
nth++;
|
||||
if (p->util)
|
||||
if (commit_to_name(p))
|
||||
continue;
|
||||
switch (n->generation) {
|
||||
case 0:
|
||||
|
@ -271,7 +289,7 @@ static void show_one_commit(struct commit *commit, int no_name)
|
|||
{
|
||||
struct strbuf pretty = STRBUF_INIT;
|
||||
const char *pretty_str = "(unavailable)";
|
||||
struct commit_name *name = commit->util;
|
||||
struct commit_name *name = commit_to_name(commit);
|
||||
|
||||
if (commit->object.parsed) {
|
||||
pp_commit_easy(CMIT_FMT_ONELINE, commit, &pretty);
|
||||
|
@ -660,6 +678,8 @@ int cmd_show_branch(int ac, const char **av, const char *prefix)
|
|||
OPT_END()
|
||||
};
|
||||
|
||||
init_commit_name_slab(&name_slab);
|
||||
|
||||
git_config(git_show_branch_config, NULL);
|
||||
|
||||
/* If nothing is specified, try the default first */
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
#ifndef COMMIT_SLAB_HDR_H
|
||||
#define COMMIT_SLAB_HDR_H
|
||||
|
||||
/* allocate ~512kB at once, allowing for malloc overhead */
|
||||
#ifndef COMMIT_SLAB_SIZE
|
||||
#define COMMIT_SLAB_SIZE (512*1024-32)
|
||||
#endif
|
||||
|
||||
#define declare_commit_slab(slabname, elemtype) \
|
||||
\
|
||||
struct slabname { \
|
||||
unsigned slab_size; \
|
||||
unsigned stride; \
|
||||
unsigned slab_count; \
|
||||
elemtype **slab; \
|
||||
}
|
||||
|
||||
/*
|
||||
* Statically initialize a commit slab named "var". Note that this
|
||||
* evaluates "stride" multiple times! Example:
|
||||
*
|
||||
* struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
|
||||
*
|
||||
*/
|
||||
#define COMMIT_SLAB_INIT(stride, var) { \
|
||||
COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
|
||||
(stride), 0, NULL \
|
||||
}
|
||||
|
||||
#define declare_commit_slab_prototypes(slabname, elemtype) \
|
||||
\
|
||||
void init_ ##slabname## _with_stride(struct slabname *s, unsigned stride); \
|
||||
void init_ ##slabname(struct slabname *s); \
|
||||
void clear_ ##slabname(struct slabname *s); \
|
||||
elemtype *slabname## _at_peek(struct slabname *s, const struct commit *c, int add_if_missing); \
|
||||
elemtype *slabname## _at(struct slabname *s, const struct commit *c); \
|
||||
elemtype *slabname## _peek(struct slabname *s, const struct commit *c)
|
||||
|
||||
#define define_shared_commit_slab(slabname, elemtype) \
|
||||
declare_commit_slab(slabname, elemtype); \
|
||||
declare_commit_slab_prototypes(slabname, elemtype)
|
||||
|
||||
#endif /* COMMIT_SLAB_HDR_H */
|
|
@ -0,0 +1,97 @@
|
|||
#ifndef COMMIT_SLAB_IMPL_H
|
||||
#define COMMIT_SLAB_IMPL_H
|
||||
|
||||
#define MAYBE_UNUSED __attribute__((__unused__))
|
||||
|
||||
#define implement_static_commit_slab(slabname, elemtype) \
|
||||
implement_commit_slab(slabname, elemtype, static MAYBE_UNUSED)
|
||||
|
||||
#define implement_shared_commit_slab(slabname, elemtype) \
|
||||
implement_commit_slab(slabname, elemtype, )
|
||||
|
||||
#define implement_commit_slab(slabname, elemtype, scope) \
|
||||
\
|
||||
static int stat_ ##slabname## realloc; \
|
||||
\
|
||||
scope void init_ ##slabname## _with_stride(struct slabname *s, \
|
||||
unsigned stride) \
|
||||
{ \
|
||||
unsigned int elem_size; \
|
||||
if (!stride) \
|
||||
stride = 1; \
|
||||
s->stride = stride; \
|
||||
elem_size = sizeof(elemtype) * stride; \
|
||||
s->slab_size = COMMIT_SLAB_SIZE / elem_size; \
|
||||
s->slab_count = 0; \
|
||||
s->slab = NULL; \
|
||||
} \
|
||||
\
|
||||
scope void init_ ##slabname(struct slabname *s) \
|
||||
{ \
|
||||
init_ ##slabname## _with_stride(s, 1); \
|
||||
} \
|
||||
\
|
||||
scope void clear_ ##slabname(struct slabname *s) \
|
||||
{ \
|
||||
unsigned int i; \
|
||||
for (i = 0; i < s->slab_count; i++) \
|
||||
free(s->slab[i]); \
|
||||
s->slab_count = 0; \
|
||||
FREE_AND_NULL(s->slab); \
|
||||
} \
|
||||
\
|
||||
scope elemtype *slabname## _at_peek(struct slabname *s, \
|
||||
const struct commit *c, \
|
||||
int add_if_missing) \
|
||||
{ \
|
||||
unsigned int nth_slab, nth_slot; \
|
||||
\
|
||||
nth_slab = c->index / s->slab_size; \
|
||||
nth_slot = c->index % s->slab_size; \
|
||||
\
|
||||
if (s->slab_count <= nth_slab) { \
|
||||
unsigned int i; \
|
||||
if (!add_if_missing) \
|
||||
return NULL; \
|
||||
REALLOC_ARRAY(s->slab, nth_slab + 1); \
|
||||
stat_ ##slabname## realloc++; \
|
||||
for (i = s->slab_count; i <= nth_slab; i++) \
|
||||
s->slab[i] = NULL; \
|
||||
s->slab_count = nth_slab + 1; \
|
||||
} \
|
||||
if (!s->slab[nth_slab]) { \
|
||||
if (!add_if_missing) \
|
||||
return NULL; \
|
||||
s->slab[nth_slab] = xcalloc(s->slab_size, \
|
||||
sizeof(**s->slab) * s->stride); \
|
||||
} \
|
||||
return &s->slab[nth_slab][nth_slot * s->stride]; \
|
||||
} \
|
||||
\
|
||||
scope elemtype *slabname## _at(struct slabname *s, \
|
||||
const struct commit *c) \
|
||||
{ \
|
||||
return slabname##_at_peek(s, c, 1); \
|
||||
} \
|
||||
\
|
||||
scope elemtype *slabname## _peek(struct slabname *s, \
|
||||
const struct commit *c) \
|
||||
{ \
|
||||
return slabname##_at_peek(s, c, 0); \
|
||||
} \
|
||||
\
|
||||
struct slabname
|
||||
|
||||
/*
|
||||
* Note that this redundant forward declaration is required
|
||||
* to allow a terminating semicolon, which makes instantiations look
|
||||
* like function declarations. I.e., the expansion of
|
||||
*
|
||||
* implement_commit_slab(indegree, int, static);
|
||||
*
|
||||
* ends in 'struct indegree;'. This would otherwise
|
||||
* be a syntax error according (at least) to ISO C. It's hard to
|
||||
* catch because GCC silently parses it by default.
|
||||
*/
|
||||
|
||||
#endif /* COMMIT_SLAB_IMPL_H */
|
113
commit-slab.h
113
commit-slab.h
|
@ -1,6 +1,9 @@
|
|||
#ifndef COMMIT_SLAB_H
|
||||
#define COMMIT_SLAB_H
|
||||
|
||||
#include "commit-slab-decl.h"
|
||||
#include "commit-slab-impl.h"
|
||||
|
||||
/*
|
||||
* define_commit_slab(slabname, elemtype) creates boilerplate code to define
|
||||
* a new struct (struct slabname) that is used to associate a piece of data
|
||||
|
@ -41,114 +44,8 @@
|
|||
* leaking memory.
|
||||
*/
|
||||
|
||||
/* allocate ~512kB at once, allowing for malloc overhead */
|
||||
#ifndef COMMIT_SLAB_SIZE
|
||||
#define COMMIT_SLAB_SIZE (512*1024-32)
|
||||
#endif
|
||||
|
||||
#define MAYBE_UNUSED __attribute__((__unused__))
|
||||
|
||||
#define define_commit_slab(slabname, elemtype) \
|
||||
\
|
||||
struct slabname { \
|
||||
unsigned slab_size; \
|
||||
unsigned stride; \
|
||||
unsigned slab_count; \
|
||||
elemtype **slab; \
|
||||
}; \
|
||||
static int stat_ ##slabname## realloc; \
|
||||
\
|
||||
static MAYBE_UNUSED void init_ ##slabname## _with_stride(struct slabname *s, \
|
||||
unsigned stride) \
|
||||
{ \
|
||||
unsigned int elem_size; \
|
||||
if (!stride) \
|
||||
stride = 1; \
|
||||
s->stride = stride; \
|
||||
elem_size = sizeof(elemtype) * stride; \
|
||||
s->slab_size = COMMIT_SLAB_SIZE / elem_size; \
|
||||
s->slab_count = 0; \
|
||||
s->slab = NULL; \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED void init_ ##slabname(struct slabname *s) \
|
||||
{ \
|
||||
init_ ##slabname## _with_stride(s, 1); \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED void clear_ ##slabname(struct slabname *s) \
|
||||
{ \
|
||||
unsigned int i; \
|
||||
for (i = 0; i < s->slab_count; i++) \
|
||||
free(s->slab[i]); \
|
||||
s->slab_count = 0; \
|
||||
FREE_AND_NULL(s->slab); \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED elemtype *slabname## _at_peek(struct slabname *s, \
|
||||
const struct commit *c, \
|
||||
int add_if_missing) \
|
||||
{ \
|
||||
unsigned int nth_slab, nth_slot; \
|
||||
\
|
||||
nth_slab = c->index / s->slab_size; \
|
||||
nth_slot = c->index % s->slab_size; \
|
||||
\
|
||||
if (s->slab_count <= nth_slab) { \
|
||||
unsigned int i; \
|
||||
if (!add_if_missing) \
|
||||
return NULL; \
|
||||
REALLOC_ARRAY(s->slab, nth_slab + 1); \
|
||||
stat_ ##slabname## realloc++; \
|
||||
for (i = s->slab_count; i <= nth_slab; i++) \
|
||||
s->slab[i] = NULL; \
|
||||
s->slab_count = nth_slab + 1; \
|
||||
} \
|
||||
if (!s->slab[nth_slab]) { \
|
||||
if (!add_if_missing) \
|
||||
return NULL; \
|
||||
s->slab[nth_slab] = xcalloc(s->slab_size, \
|
||||
sizeof(**s->slab) * s->stride); \
|
||||
} \
|
||||
return &s->slab[nth_slab][nth_slot * s->stride]; \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED elemtype *slabname## _at(struct slabname *s, \
|
||||
const struct commit *c) \
|
||||
{ \
|
||||
return slabname##_at_peek(s, c, 1); \
|
||||
} \
|
||||
\
|
||||
static MAYBE_UNUSED elemtype *slabname## _peek(struct slabname *s, \
|
||||
const struct commit *c) \
|
||||
{ \
|
||||
return slabname##_at_peek(s, c, 0); \
|
||||
} \
|
||||
\
|
||||
struct slabname
|
||||
|
||||
/*
|
||||
* Note that this redundant forward declaration is required
|
||||
* to allow a terminating semicolon, which makes instantiations look
|
||||
* like function declarations. I.e., the expansion of
|
||||
*
|
||||
* define_commit_slab(indegree, int);
|
||||
*
|
||||
* ends in 'struct indegree;'. This would otherwise
|
||||
* be a syntax error according (at least) to ISO C. It's hard to
|
||||
* catch because GCC silently parses it by default.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Statically initialize a commit slab named "var". Note that this
|
||||
* evaluates "stride" multiple times! Example:
|
||||
*
|
||||
* struct indegree indegrees = COMMIT_SLAB_INIT(1, indegrees);
|
||||
*
|
||||
*/
|
||||
#define COMMIT_SLAB_INIT(stride, var) { \
|
||||
COMMIT_SLAB_SIZE / sizeof(**((var).slab)) / (stride), \
|
||||
(stride), 0, NULL \
|
||||
}
|
||||
declare_commit_slab(slabname, elemtype); \
|
||||
implement_static_commit_slab(slabname, elemtype)
|
||||
|
||||
#endif /* COMMIT_SLAB_H */
|
||||
|
|
12
commit.c
12
commit.c
|
@ -1605,13 +1605,21 @@ out:
|
|||
return result;
|
||||
}
|
||||
|
||||
define_commit_slab(merge_desc_slab, struct merge_remote_desc *);
|
||||
static struct merge_desc_slab merge_desc_slab = COMMIT_SLAB_INIT(1, merge_desc_slab);
|
||||
|
||||
struct merge_remote_desc *merge_remote_util(struct commit *commit)
|
||||
{
|
||||
return *merge_desc_slab_at(&merge_desc_slab, commit);
|
||||
}
|
||||
|
||||
void set_merge_remote_desc(struct commit *commit,
|
||||
const char *name, struct object *obj)
|
||||
{
|
||||
struct merge_remote_desc *desc;
|
||||
FLEX_ALLOC_STR(desc, name, name);
|
||||
desc->obj = obj;
|
||||
commit->util = desc;
|
||||
*merge_desc_slab_at(&merge_desc_slab, commit) = desc;
|
||||
}
|
||||
|
||||
struct commit *get_merge_parent(const char *name)
|
||||
|
@ -1623,7 +1631,7 @@ struct commit *get_merge_parent(const char *name)
|
|||
return NULL;
|
||||
obj = parse_object(&oid);
|
||||
commit = (struct commit *)peel_to_type(name, 0, obj, OBJ_COMMIT);
|
||||
if (commit && !commit->util)
|
||||
if (commit && !merge_remote_util(commit))
|
||||
set_merge_remote_desc(commit, name, obj);
|
||||
return commit;
|
||||
}
|
||||
|
|
8
commit.h
8
commit.h
|
@ -16,9 +16,13 @@ struct commit_list {
|
|||
struct commit_list *next;
|
||||
};
|
||||
|
||||
/*
|
||||
* The size of this struct matters in full repo walk operations like
|
||||
* 'git clone' or 'git gc'. Consider using commit-slab to attach data
|
||||
* to a commit instead of adding new fields here.
|
||||
*/
|
||||
struct commit {
|
||||
struct object object;
|
||||
void *util;
|
||||
timestamp_t date;
|
||||
struct commit_list *parents;
|
||||
|
||||
|
@ -312,7 +316,7 @@ struct merge_remote_desc {
|
|||
struct object *obj; /* the named object, could be a tag */
|
||||
char name[FLEX_ARRAY];
|
||||
};
|
||||
#define merge_remote_util(commit) ((struct merge_remote_desc *)((commit)->util))
|
||||
extern struct merge_remote_desc *merge_remote_util(struct commit *);
|
||||
extern void set_merge_remote_desc(struct commit *commit,
|
||||
const char *name, struct object *obj);
|
||||
|
||||
|
|
|
@ -295,8 +295,12 @@ void show_decorations(struct rev_info *opt, struct commit *commit)
|
|||
{
|
||||
struct strbuf sb = STRBUF_INIT;
|
||||
|
||||
if (opt->show_source && commit->util)
|
||||
fprintf(opt->diffopt.file, "\t%s", (char *) commit->util);
|
||||
if (opt->sources) {
|
||||
char **slot = revision_sources_peek(opt->sources, commit);
|
||||
|
||||
if (slot && *slot)
|
||||
fprintf(opt->diffopt.file, "\t%s", *slot);
|
||||
}
|
||||
if (!opt->show_decorations)
|
||||
return;
|
||||
format_decorations(&sb, commit, opt->diffopt.use_color);
|
||||
|
|
|
@ -286,10 +286,12 @@ static void output(struct merge_options *o, int v, const char *fmt, ...)
|
|||
|
||||
static void output_commit_title(struct merge_options *o, struct commit *commit)
|
||||
{
|
||||
struct merge_remote_desc *desc;
|
||||
|
||||
strbuf_addchars(&o->obuf, ' ', o->call_depth * 2);
|
||||
if (commit->util)
|
||||
strbuf_addf(&o->obuf, "virtual %s\n",
|
||||
merge_remote_util(commit)->name);
|
||||
desc = merge_remote_util(commit);
|
||||
if (desc)
|
||||
strbuf_addf(&o->obuf, "virtual %s\n", desc->name);
|
||||
else {
|
||||
strbuf_add_unique_abbrev(&o->obuf, &commit->object.oid,
|
||||
DEFAULT_ABBREV);
|
||||
|
|
1
object.h
1
object.h
|
@ -42,6 +42,7 @@ struct object_array {
|
|||
* builtin/index-pack.c: 2021
|
||||
* builtin/pack-objects.c: 20
|
||||
* builtin/reflog.c: 10--12
|
||||
* builtin/show-branch.c: 0-------------------------------------------26
|
||||
* builtin/unpack-objects.c: 2021
|
||||
*/
|
||||
#define FLAG_BITS 27
|
||||
|
|
19
revision.c
19
revision.c
|
@ -29,6 +29,8 @@ volatile show_early_output_fn_t show_early_output;
|
|||
static const char *term_bad;
|
||||
static const char *term_good;
|
||||
|
||||
implement_shared_commit_slab(revision_sources, char *);
|
||||
|
||||
void show_object_with_name(FILE *out, struct object *obj, const char *name)
|
||||
{
|
||||
const char *p;
|
||||
|
@ -265,14 +267,19 @@ static struct commit *handle_commit(struct rev_info *revs,
|
|||
*/
|
||||
if (object->type == OBJ_COMMIT) {
|
||||
struct commit *commit = (struct commit *)object;
|
||||
|
||||
if (parse_commit(commit) < 0)
|
||||
die("unable to parse commit %s", name);
|
||||
if (flags & UNINTERESTING) {
|
||||
mark_parents_uninteresting(commit);
|
||||
revs->limited = 1;
|
||||
}
|
||||
if (revs->show_source && !commit->util)
|
||||
commit->util = xstrdup(name);
|
||||
if (revs->sources) {
|
||||
char **slot = revision_sources_at(revs->sources, commit);
|
||||
|
||||
if (!*slot)
|
||||
*slot = xstrdup(name);
|
||||
}
|
||||
return commit;
|
||||
}
|
||||
|
||||
|
@ -824,8 +831,12 @@ static int add_parents_to_list(struct rev_info *revs, struct commit *commit,
|
|||
}
|
||||
return -1;
|
||||
}
|
||||
if (revs->show_source && !p->util)
|
||||
p->util = commit->util;
|
||||
if (revs->sources) {
|
||||
char **slot = revision_sources_at(revs->sources, p);
|
||||
|
||||
if (!*slot)
|
||||
*slot = *revision_sources_at(revs->sources, commit);
|
||||
}
|
||||
p->object.flags |= left_flag;
|
||||
if (!(p->object.flags & SEEN)) {
|
||||
p->object.flags |= SEEN;
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
#include "notes.h"
|
||||
#include "pretty.h"
|
||||
#include "diff.h"
|
||||
#include "commit-slab-decl.h"
|
||||
|
||||
/* Remember to update object flag allocation in object.h */
|
||||
#define SEEN (1u<<0)
|
||||
|
@ -29,6 +30,7 @@ struct rev_info;
|
|||
struct log_info;
|
||||
struct string_list;
|
||||
struct saved_parents;
|
||||
define_shared_commit_slab(revision_sources, char *);
|
||||
|
||||
struct rev_cmdline_info {
|
||||
unsigned int nr;
|
||||
|
@ -111,7 +113,6 @@ struct rev_info {
|
|||
right_only:1,
|
||||
rewrite_parents:1,
|
||||
print_parents:1,
|
||||
show_source:1,
|
||||
show_decorations:1,
|
||||
reverse:1,
|
||||
reverse_output_stage:1,
|
||||
|
@ -224,6 +225,8 @@ struct rev_info {
|
|||
|
||||
struct commit_list *previous_parents;
|
||||
const char *break_bar;
|
||||
|
||||
struct revision_sources *sources;
|
||||
};
|
||||
|
||||
extern int ref_excluded(struct string_list *, const char *path);
|
||||
|
|
24
sequencer.c
24
sequencer.c
|
@ -27,6 +27,7 @@
|
|||
#include "worktree.h"
|
||||
#include "oidmap.h"
|
||||
#include "oidset.h"
|
||||
#include "commit-slab.h"
|
||||
#include "alias.h"
|
||||
|
||||
#define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
|
||||
|
@ -4238,6 +4239,7 @@ static enum check_level get_missing_commit_check_level(void)
|
|||
return CHECK_IGNORE;
|
||||
}
|
||||
|
||||
define_commit_slab(commit_seen, unsigned char);
|
||||
/*
|
||||
* Check if the user dropped some commits by mistake
|
||||
* Behaviour determined by rebase.missingCommitsCheck.
|
||||
|
@ -4251,6 +4253,9 @@ int check_todo_list(void)
|
|||
struct todo_list todo_list = TODO_LIST_INIT;
|
||||
struct strbuf missing = STRBUF_INIT;
|
||||
int advise_to_edit_todo = 0, res = 0, i;
|
||||
struct commit_seen commit_seen;
|
||||
|
||||
init_commit_seen(&commit_seen);
|
||||
|
||||
strbuf_addstr(&todo_file, rebase_path_todo());
|
||||
if (strbuf_read_file_or_whine(&todo_list.buf, todo_file.buf) < 0) {
|
||||
|
@ -4267,7 +4272,7 @@ int check_todo_list(void)
|
|||
for (i = 0; i < todo_list.nr; i++) {
|
||||
struct commit *commit = todo_list.items[i].commit;
|
||||
if (commit)
|
||||
commit->util = (void *)1;
|
||||
*commit_seen_at(&commit_seen, commit) = 1;
|
||||
}
|
||||
|
||||
todo_list_release(&todo_list);
|
||||
|
@ -4283,11 +4288,11 @@ int check_todo_list(void)
|
|||
for (i = todo_list.nr - 1; i >= 0; i--) {
|
||||
struct todo_item *item = todo_list.items + i;
|
||||
struct commit *commit = item->commit;
|
||||
if (commit && !commit->util) {
|
||||
if (commit && !*commit_seen_at(&commit_seen, commit)) {
|
||||
strbuf_addf(&missing, " - %s %.*s\n",
|
||||
short_commit_name(commit),
|
||||
item->arg_len, item->arg);
|
||||
commit->util = (void *)1;
|
||||
*commit_seen_at(&commit_seen, commit) = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4313,6 +4318,7 @@ int check_todo_list(void)
|
|||
"The possible behaviours are: ignore, warn, error.\n\n"));
|
||||
|
||||
leave_check:
|
||||
clear_commit_seen(&commit_seen);
|
||||
strbuf_release(&todo_file);
|
||||
todo_list_release(&todo_list);
|
||||
|
||||
|
@ -4433,6 +4439,8 @@ static int subject2item_cmp(const void *fndata,
|
|||
return key ? strcmp(a->subject, key) : strcmp(a->subject, b->subject);
|
||||
}
|
||||
|
||||
define_commit_slab(commit_todo_item, struct todo_item *);
|
||||
|
||||
/*
|
||||
* Rearrange the todo list that has both "pick commit-id msg" and "pick
|
||||
* commit-id fixup!/squash! msg" in it so that the latter is put immediately
|
||||
|
@ -4449,6 +4457,7 @@ int rearrange_squash(void)
|
|||
struct hashmap subject2item;
|
||||
int res = 0, rearranged = 0, *next, *tail, i;
|
||||
char **subjects;
|
||||
struct commit_todo_item commit_todo;
|
||||
|
||||
if (strbuf_read_file_or_whine(&todo_list.buf, todo_file) < 0)
|
||||
return -1;
|
||||
|
@ -4457,6 +4466,7 @@ int rearrange_squash(void)
|
|||
return -1;
|
||||
}
|
||||
|
||||
init_commit_todo_item(&commit_todo);
|
||||
/*
|
||||
* The hashmap maps onelines to the respective todo list index.
|
||||
*
|
||||
|
@ -4487,10 +4497,11 @@ int rearrange_squash(void)
|
|||
|
||||
if (is_fixup(item->command)) {
|
||||
todo_list_release(&todo_list);
|
||||
clear_commit_todo_item(&commit_todo);
|
||||
return error(_("the script was already rearranged."));
|
||||
}
|
||||
|
||||
item->commit->util = item;
|
||||
*commit_todo_item_at(&commit_todo, item->commit) = item;
|
||||
|
||||
parse_commit(item->commit);
|
||||
commit_buffer = get_commit_buffer(item->commit, NULL);
|
||||
|
@ -4517,9 +4528,9 @@ int rearrange_squash(void)
|
|||
else if (!strchr(p, ' ') &&
|
||||
(commit2 =
|
||||
lookup_commit_reference_by_name(p)) &&
|
||||
commit2->util)
|
||||
*commit_todo_item_at(&commit_todo, commit2))
|
||||
/* found by commit name */
|
||||
i2 = (struct todo_item *)commit2->util
|
||||
i2 = *commit_todo_item_at(&commit_todo, commit2)
|
||||
- todo_list.items;
|
||||
else {
|
||||
/* copy can be a prefix of the commit subject */
|
||||
|
@ -4596,5 +4607,6 @@ int rearrange_squash(void)
|
|||
hashmap_free(&subject2item, 1);
|
||||
todo_list_release(&todo_list);
|
||||
|
||||
clear_commit_todo_item(&commit_todo);
|
||||
return res;
|
||||
}
|
||||
|
|
40
shallow.c
40
shallow.c
|
@ -12,6 +12,7 @@
|
|||
#include "commit-slab.h"
|
||||
#include "revision.h"
|
||||
#include "list-objects.h"
|
||||
#include "commit-slab.h"
|
||||
|
||||
static int is_shallow = -1;
|
||||
static struct stat_validity shallow_stat;
|
||||
|
@ -74,6 +75,11 @@ int is_repository_shallow(void)
|
|||
return is_shallow;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO: use "int" elemtype instead of "int *" when/if commit-slab
|
||||
* supports a "valid" flag.
|
||||
*/
|
||||
define_commit_slab(commit_depth, int *);
|
||||
struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
||||
int shallow_flag, int not_shallow_flag)
|
||||
{
|
||||
|
@ -82,25 +88,29 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
|||
struct object_array stack = OBJECT_ARRAY_INIT;
|
||||
struct commit *commit = NULL;
|
||||
struct commit_graft *graft;
|
||||
struct commit_depth depths;
|
||||
|
||||
init_commit_depth(&depths);
|
||||
while (commit || i < heads->nr || stack.nr) {
|
||||
struct commit_list *p;
|
||||
if (!commit) {
|
||||
if (i < heads->nr) {
|
||||
int **depth_slot;
|
||||
commit = (struct commit *)
|
||||
deref_tag(heads->objects[i++].item, NULL, 0);
|
||||
if (!commit || commit->object.type != OBJ_COMMIT) {
|
||||
commit = NULL;
|
||||
continue;
|
||||
}
|
||||
if (!commit->util)
|
||||
commit->util = xmalloc(sizeof(int));
|
||||
*(int *)commit->util = 0;
|
||||
depth_slot = commit_depth_at(&depths, commit);
|
||||
if (!*depth_slot)
|
||||
*depth_slot = xmalloc(sizeof(int));
|
||||
**depth_slot = 0;
|
||||
cur_depth = 0;
|
||||
} else {
|
||||
commit = (struct commit *)
|
||||
object_array_pop(&stack);
|
||||
cur_depth = *(int *)commit->util;
|
||||
cur_depth = **commit_depth_at(&depths, commit);
|
||||
}
|
||||
}
|
||||
parse_commit_or_die(commit);
|
||||
|
@ -116,25 +126,31 @@ struct commit_list *get_shallow_commits(struct object_array *heads, int depth,
|
|||
}
|
||||
commit->object.flags |= not_shallow_flag;
|
||||
for (p = commit->parents, commit = NULL; p; p = p->next) {
|
||||
if (!p->item->util) {
|
||||
int *pointer = xmalloc(sizeof(int));
|
||||
p->item->util = pointer;
|
||||
*pointer = cur_depth;
|
||||
int **depth_slot = commit_depth_at(&depths, p->item);
|
||||
if (!*depth_slot) {
|
||||
*depth_slot = xmalloc(sizeof(int));
|
||||
**depth_slot = cur_depth;
|
||||
} else {
|
||||
int *pointer = p->item->util;
|
||||
if (cur_depth >= *pointer)
|
||||
if (cur_depth >= **depth_slot)
|
||||
continue;
|
||||
*pointer = cur_depth;
|
||||
**depth_slot = cur_depth;
|
||||
}
|
||||
if (p->next)
|
||||
add_object_array(&p->item->object,
|
||||
NULL, &stack);
|
||||
else {
|
||||
commit = p->item;
|
||||
cur_depth = *(int *)commit->util;
|
||||
cur_depth = **commit_depth_at(&depths, commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (i = 0; i < depths.slab_count; i++) {
|
||||
int j;
|
||||
|
||||
for (j = 0; j < depths.slab_size; j++)
|
||||
free(depths.slab[i][j]);
|
||||
}
|
||||
clear_commit_depth(&depths);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче