summaryrefslogtreecommitdiff
path: root/object-name.c
diff options
context:
space:
mode:
Diffstat (limited to 'object-name.c')
-rw-r--r--object-name.c145
1 files changed, 108 insertions, 37 deletions
diff --git a/object-name.c b/object-name.c
index 88d1313028..11aa0e6afc 100644
--- a/object-name.c
+++ b/object-name.c
@@ -19,7 +19,7 @@
#include "oidtree.h"
#include "packfile.h"
#include "pretty.h"
-#include "object-store-ll.h"
+#include "object-file.h"
#include "read-cache-ll.h"
#include "repo-settings.h"
#include "repository.h"
@@ -28,6 +28,7 @@
#include "commit-reach.h"
#include "date.h"
#include "object-file-convert.h"
+#include "prio-queue.h"
static int get_oid_oneline(struct repository *r, const char *, struct object_id *,
const struct commit_list *);
@@ -112,10 +113,10 @@ static enum cb_next match_prefix(const struct object_id *oid, void *arg)
static void find_short_object_filename(struct disambiguate_state *ds)
{
- struct object_directory *odb;
+ struct odb_source *source;
- for (odb = ds->repo->objects->odb; odb && !ds->ambiguous; odb = odb->next)
- oidtree_each(odb_loose_cache(odb, &ds->bin_pfx),
+ for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next)
+ oidtree_each(odb_loose_cache(source, &ds->bin_pfx),
&ds->bin_pfx, ds->len, match_prefix, ds);
}
@@ -198,16 +199,20 @@ static void unique_in_pack(struct packed_git *p,
static void find_short_packed_object(struct disambiguate_state *ds)
{
- struct multi_pack_index *m;
+ struct odb_source *source;
struct packed_git *p;
/* Skip, unless oids from the storage hash algorithm are wanted */
if (ds->bin_pfx.algo && (&hash_algos[ds->bin_pfx.algo] != ds->repo->hash_algo))
return;
- for (m = get_multi_pack_index(ds->repo); m && !ds->ambiguous;
- m = m->next)
- unique_in_midx(m, ds);
+ odb_prepare_alternates(ds->repo->objects);
+ for (source = ds->repo->objects->sources; source && !ds->ambiguous; source = source->next) {
+ struct multi_pack_index *m = get_multi_pack_index(source);
+ if (m)
+ unique_in_midx(m, ds);
+ }
+
for (p = get_packed_git(ds->repo); p && !ds->ambiguous;
p = p->next)
unique_in_pack(p, ds);
@@ -251,7 +256,7 @@ static int disambiguate_commit_only(struct repository *r,
const struct object_id *oid,
void *cb_data UNUSED)
{
- int kind = oid_object_info(r, oid, NULL);
+ int kind = odb_read_object_info(r->objects, oid, NULL);
return kind == OBJ_COMMIT;
}
@@ -262,7 +267,7 @@ static int disambiguate_committish_only(struct repository *r,
struct object *obj;
int kind;
- kind = oid_object_info(r, oid, NULL);
+ kind = odb_read_object_info(r->objects, oid, NULL);
if (kind == OBJ_COMMIT)
return 1;
if (kind != OBJ_TAG)
@@ -279,7 +284,7 @@ static int disambiguate_tree_only(struct repository *r,
const struct object_id *oid,
void *cb_data UNUSED)
{
- int kind = oid_object_info(r, oid, NULL);
+ int kind = odb_read_object_info(r->objects, oid, NULL);
return kind == OBJ_TREE;
}
@@ -290,7 +295,7 @@ static int disambiguate_treeish_only(struct repository *r,
struct object *obj;
int kind;
- kind = oid_object_info(r, oid, NULL);
+ kind = odb_read_object_info(r->objects, oid, NULL);
if (kind == OBJ_TREE || kind == OBJ_COMMIT)
return 1;
if (kind != OBJ_TAG)
@@ -307,7 +312,7 @@ static int disambiguate_blob_only(struct repository *r,
const struct object_id *oid,
void *cb_data UNUSED)
{
- int kind = oid_object_info(r, oid, NULL);
+ int kind = odb_read_object_info(r->objects, oid, NULL);
return kind == OBJ_BLOB;
}
@@ -376,7 +381,7 @@ static int init_object_disambiguation(struct repository *r,
ds->hex_pfx[len] = '\0';
ds->repo = r;
ds->bin_pfx.algo = algo ? hash_algo_by_ptr(algo) : GIT_HASH_UNKNOWN;
- prepare_alt_odb(r);
+ odb_prepare_alternates(r->objects);
return 0;
}
@@ -399,7 +404,7 @@ static int show_ambiguous_object(const struct object_id *oid, void *data)
return 0;
hash = repo_find_unique_abbrev(ds->repo, oid, DEFAULT_ABBREV);
- type = oid_object_info(ds->repo, oid, NULL);
+ type = odb_read_object_info(ds->repo->objects, oid, NULL);
if (type < 0) {
/*
@@ -514,8 +519,8 @@ static int sort_ambiguous(const void *va, const void *vb, void *ctx)
{
struct repository *sort_ambiguous_repo = ctx;
const struct object_id *a = va, *b = vb;
- int a_type = oid_object_info(sort_ambiguous_repo, a, NULL);
- int b_type = oid_object_info(sort_ambiguous_repo, b, NULL);
+ int a_type = odb_read_object_info(sort_ambiguous_repo->objects, a, NULL);
+ int b_type = odb_read_object_info(sort_ambiguous_repo->objects, b, NULL);
int a_type_sort;
int b_type_sort;
@@ -792,11 +797,15 @@ static void find_abbrev_len_for_pack(struct packed_git *p,
static void find_abbrev_len_packed(struct min_abbrev_data *mad)
{
- struct multi_pack_index *m;
struct packed_git *p;
- for (m = get_multi_pack_index(mad->repo); m; m = m->next)
- find_abbrev_len_for_midx(m, mad);
+ odb_prepare_alternates(mad->repo->objects);
+ for (struct odb_source *source = mad->repo->objects->sources; source; source = source->next) {
+ struct multi_pack_index *m = get_multi_pack_index(source);
+ if (m)
+ find_abbrev_len_for_midx(m, mad);
+ }
+
for (p = get_packed_git(mad->repo); p; p = p->next)
find_abbrev_len_for_pack(p, mad);
}
@@ -961,7 +970,9 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
int fatal = !(flags & GET_OID_QUIETLY);
if (len == r->hash_algo->hexsz && !get_oid_hex(str, oid)) {
- if (repo_settings_get_warn_ambiguous_refs(r) && warn_on_object_refname_ambiguity) {
+ if (!(flags & GET_OID_SKIP_AMBIGUITY_CHECK) &&
+ repo_settings_get_warn_ambiguous_refs(r) &&
+ warn_on_object_refname_ambiguity) {
refs_found = repo_dwim_ref(r, str, len, &tmp_oid, &real_ref, 0);
if (refs_found > 0) {
warning(warn_msg, len, str);
@@ -1079,13 +1090,17 @@ static int get_oid_basic(struct repository *r, const char *str, int len,
* still fill in the oid with the "old" value,
* which we can use.
*/
- } else {
+ } else if (!(flags & GET_OID_GENTLY)) {
if (flags & GET_OID_QUIETLY) {
exit(128);
}
die(_("log for '%.*s' only has %d entries"),
len, str, co_cnt);
}
+ if (flags & GET_OID_GENTLY) {
+ free(real_ref);
+ return -1;
+ }
}
}
@@ -1272,6 +1287,58 @@ static int peel_onion(struct repository *r, const char *name, int len,
return 0;
}
+/*
+ * Documentation/revisions.adoc says:
+ * '<describeOutput>', e.g. 'v1.7.4.2-679-g3bee7fb'::
+ * Output from `git describe`; i.e. a closest tag, optionally
+ * followed by a dash and a number of commits, followed by a dash, a
+ * 'g', and an abbreviated object name.
+ *
+ * which means that the stuff before '-g${HASH}' needs to be a valid
+ * refname, a dash, and a non-negative integer. This function verifies
+ * that.
+ *
+ * In particular, we do not want to treat
+ * branchname:path/to/file/named/i-gaffed
+ * as a request for commit affed.
+ *
+ * More generally, we should probably not treat
+ * 'refs/heads/./../.../ ~^:/?*[////\\\&}/busted.lock-g050e0ef6ead'
+ * as a request for object 050e0ef6ead either.
+ *
+ * We are called with name[len] == '-' and name[len+1] == 'g', i.e.
+ * we are verifying ${REFNAME}-{INTEGER} part of the name.
+ */
+static int ref_and_count_parts_valid(const char *name, int len)
+{
+ struct strbuf sb;
+ const char *cp;
+ int flags = REFNAME_ALLOW_ONELEVEL;
+ int ret = 1;
+
+ /* Ensure we have at least one digit */
+ if (!isxdigit(name[len-1]))
+ return 0;
+
+ /* Skip over digits backwards until we get to the dash */
+ for (cp = name + len - 2; name < cp; cp--) {
+ if (*cp == '-')
+ break;
+ if (!isxdigit(*cp))
+ return 0;
+ }
+ /* Ensure we found the leading dash */
+ if (*cp != '-')
+ return 0;
+
+ len = cp - name;
+ strbuf_init(&sb, len);
+ strbuf_add(&sb, name, len);
+ ret = !check_refname_format(sb.buf, flags);
+ strbuf_release(&sb);
+ return ret;
+}
+
static int get_describe_name(struct repository *r,
const char *name, int len,
struct object_id *oid)
@@ -1285,7 +1352,8 @@ static int get_describe_name(struct repository *r,
/* We must be looking at g in "SOMETHING-g"
* for it to be describe output.
*/
- if (ch == 'g' && cp[-1] == '-') {
+ if (ch == 'g' && cp[-1] == '-' &&
+ ref_and_count_parts_valid(name, cp - 1 - name)) {
cp++;
len -= cp - name;
return get_short_oid(r,
@@ -1402,7 +1470,7 @@ static int get_oid_oneline(struct repository *r,
const char *prefix, struct object_id *oid,
const struct commit_list *list)
{
- struct commit_list *copy = NULL, **copy_tail = &copy;
+ struct prio_queue copy = { compare_commits_by_commit_date };
const struct commit_list *l;
int found = 0;
int negative = 0;
@@ -1424,9 +1492,9 @@ static int get_oid_oneline(struct repository *r,
for (l = list; l; l = l->next) {
l->item->object.flags |= ONELINE_SEEN;
- copy_tail = &commit_list_insert(l->item, copy_tail)->next;
+ prio_queue_put(&copy, l->item);
}
- while (copy) {
+ while (copy.nr) {
const char *p, *buf;
struct commit *commit;
int matches;
@@ -1448,7 +1516,7 @@ static int get_oid_oneline(struct repository *r,
regfree(&regex);
for (l = list; l; l = l->next)
clear_commit_marks(l->item, ONELINE_SEEN);
- free_commit_list(copy);
+ clear_prio_queue(&copy);
return found ? 0 : -1;
}
@@ -1741,18 +1809,20 @@ void object_context_release(struct object_context *ctx)
strbuf_release(&ctx->symlink_path);
}
-/*
- * This is like "get_oid_basic()", except it allows "object ID expressions",
- * notably "xyz^" for "parent of xyz"
- */
-int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
+int repo_get_oid_with_flags(struct repository *r, const char *name,
+ struct object_id *oid, unsigned flags)
{
struct object_context unused;
- int ret = get_oid_with_context(r, name, 0, oid, &unused);
+ int ret = get_oid_with_context(r, name, flags, oid, &unused);
object_context_release(&unused);
return ret;
}
+int repo_get_oid(struct repository *r, const char *name, struct object_id *oid)
+{
+ return repo_get_oid_with_flags(r, name, oid, 0);
+}
+
/*
* This returns a non-zero value if the string (built using printf
* format and the given arguments) is not a valid object.
@@ -2000,7 +2070,6 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
cb.list = &list;
refs_for_each_ref(get_main_ref_store(repo), handle_one_ref, &cb);
refs_head_ref(get_main_ref_store(repo), handle_one_ref, &cb);
- commit_list_sort_by_date(&list);
ret = get_oid_oneline(repo, name + 2, oid, list);
free_commit_list(list);
@@ -2052,12 +2121,14 @@ static enum get_oid_result get_oid_with_context_1(struct repository *repo,
return -1;
}
for (cp = name, bracket_depth = 0; *cp; cp++) {
- if (*cp == '{')
+ if (strchr("@^", *cp) && cp[1] == '{') {
+ cp++;
bracket_depth++;
- else if (bracket_depth && *cp == '}')
+ } else if (bracket_depth && *cp == '}') {
bracket_depth--;
- else if (!bracket_depth && *cp == ':')
+ } else if (!bracket_depth && *cp == ':') {
break;
+ }
}
if (*cp == ':') {
struct object_id tree_oid;