git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: "Carlos Martín Nieto" <cmn@elego.de>
Cc: git@vger.kernel.org, Albert Astals Cid <aacid@kde.org>
Subject: [PATCH 1/2] get_sha1_with_context: report features used in resolution
Date: Wed, 11 Jan 2012 14:42:10 -0500	[thread overview]
Message-ID: <20120111194210.GA12441@sigill.intra.peff.net> (raw)
In-Reply-To: <20120111193916.GA12333@sigill.intra.peff.net>

Most callers generally treat get_sha1 as a black box, giving
it a string from the user and expecting to get a sha1 in
return. The get_sha1_with_context function gives callers
more information about what happened while resolving the
object name so they can make better decisions about how to
use the result. We currently use this only to provide
information about the path entry used to find a blob.

We don't currently provide any information about the
resolution rules that were used to reach the final object.
Some callers may want these in order to enforce a policy
that a particular subset of the lookup rules are used (e.g.,
when serving remote requests).

This patch adds a set of bit-fields that document the use of
particular features during an object lookup.

Signed-off-by: Jeff King <peff@peff.net>
---
The diffstat looks a little scary, but it is mostly just the internal
get_sha1 functions learning to pass the object_context around.

 cache.h     |    7 +++++
 sha1_name.c |   73 +++++++++++++++++++++++++++++++++++++---------------------
 2 files changed, 53 insertions(+), 27 deletions(-)

diff --git a/cache.h b/cache.h
index 10afd71..ac25a37 100644
--- a/cache.h
+++ b/cache.h
@@ -809,6 +809,13 @@ struct object_context {
 	unsigned char tree[20];
 	char path[PATH_MAX];
 	unsigned mode;
+	unsigned used_ref:1,
+		 used_reflog:1,
+		 used_index:1,
+		 used_nth_checkout:1,
+		 used_describe_name:1,
+		 used_oneline:1,
+		 used_raw_hex:1;
 };
 
 extern int get_sha1(const char *str, unsigned char *sha1);
diff --git a/sha1_name.c b/sha1_name.c
index 03ffc2c..ad7c52a 100644
--- a/sha1_name.c
+++ b/sha1_name.c
@@ -7,7 +7,8 @@
 #include "refs.h"
 #include "remote.h"
 
-static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *);
+static int get_sha1_oneline(const char *, unsigned char *, struct commit_list *,
+			    struct object_context *);
 
 static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
 {
@@ -158,7 +159,7 @@ static int find_unique_short_object(int len, char *canonical,
 }
 
 static int get_short_sha1(const char *name, int len, unsigned char *sha1,
-			  int quietly)
+			  int quietly, struct object_context *oc)
 {
 	int i, status;
 	char canonical[40];
@@ -190,6 +191,8 @@ static int get_short_sha1(const char *name, int len, unsigned char *sha1,
 	status = find_unique_short_object(i, canonical, res, sha1);
 	if (!quietly && (status == SHORT_NAME_AMBIGUOUS))
 		return error("short SHA1 %.*s is ambiguous.", len, canonical);
+	if (!status)
+		oc->used_raw_hex = 1;
 	return status;
 }
 
@@ -204,7 +207,8 @@ const char *find_unique_abbrev(const unsigned char *sha1, int len)
 		return hex;
 	while (len < 40) {
 		unsigned char sha1_ret[20];
-		status = get_short_sha1(hex, len, sha1_ret, 1);
+		struct object_context unused;
+		status = get_short_sha1(hex, len, sha1_ret, 1, &unused);
 		if (exists
 		    ? !status
 		    : status == SHORT_NAME_NOT_FOUND) {
@@ -255,17 +259,21 @@ static inline int upstream_mark(const char *string, int len)
 	return 0;
 }
 
-static int get_sha1_1(const char *name, int len, unsigned char *sha1);
+static int get_sha1_1(const char *name, int len, unsigned char *sha1,
+		      struct object_context *oc);
 
-static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
+static int get_sha1_basic(const char *str, int len, unsigned char *sha1,
+			  struct object_context *oc)
 {
 	static const char *warn_msg = "refname '%.*s' is ambiguous.";
 	char *real_ref = NULL;
 	int refs_found = 0;
 	int at, reflog_len;
 
-	if (len == 40 && !get_sha1_hex(str, sha1))
+	if (len == 40 && !get_sha1_hex(str, sha1)) {
+		oc->used_raw_hex = 1;
 		return 0;
+	}
 
 	/* basic@{time or number or -number} format to query ref-log */
 	reflog_len = at = 0;
@@ -292,7 +300,8 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 		ret = interpret_branch_name(str+at, &buf);
 		if (ret > 0) {
 			/* substitute this branch name and restart */
-			return get_sha1_1(buf.buf, buf.len, sha1);
+			oc->used_nth_checkout = 1;
+			return get_sha1_1(buf.buf, buf.len, sha1, oc);
 		} else if (ret == 0) {
 			return -1;
 		}
@@ -305,6 +314,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 
 	if (!refs_found)
 		return -1;
+	oc->used_ref = 1;
 
 	if (warn_ambiguous_refs && refs_found > 1)
 		warning(warn_msg, len, str);
@@ -352,6 +362,7 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 				    len, str, co_cnt);
 			}
 		}
+		oc->used_reflog = 1;
 	}
 
 	free(real_ref);
@@ -359,10 +370,11 @@ static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
 }
 
 static int get_parent(const char *name, int len,
-		      unsigned char *result, int idx)
+		      unsigned char *result, int idx,
+		      struct object_context *oc)
 {
 	unsigned char sha1[20];
-	int ret = get_sha1_1(name, len, sha1);
+	int ret = get_sha1_1(name, len, sha1, oc);
 	struct commit *commit;
 	struct commit_list *p;
 
@@ -389,13 +401,14 @@ static int get_parent(const char *name, int len,
 }
 
 static int get_nth_ancestor(const char *name, int len,
-			    unsigned char *result, int generation)
+			    unsigned char *result, int generation,
+			    struct object_context *oc)
 {
 	unsigned char sha1[20];
 	struct commit *commit;
 	int ret;
 
-	ret = get_sha1_1(name, len, sha1);
+	ret = get_sha1_1(name, len, sha1, oc);
 	if (ret)
 		return ret;
 	commit = lookup_commit_reference(sha1);
@@ -436,7 +449,8 @@ struct object *peel_to_type(const char *name, int namelen,
 	}
 }
 
-static int peel_onion(const char *name, int len, unsigned char *sha1)
+static int peel_onion(const char *name, int len, unsigned char *sha1,
+		      struct object_context *oc)
 {
 	unsigned char outer[20];
 	const char *sp;
@@ -476,7 +490,7 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
 	else
 		return -1;
 
-	if (get_sha1_1(name, sp - name - 2, outer))
+	if (get_sha1_1(name, sp - name - 2, outer, oc))
 		return -1;
 
 	o = parse_object(outer);
@@ -515,14 +529,15 @@ static int peel_onion(const char *name, int len, unsigned char *sha1)
 
 		prefix = xstrndup(sp + 1, name + len - 1 - (sp + 1));
 		commit_list_insert((struct commit *)o, &list);
-		ret = get_sha1_oneline(prefix, sha1, list);
+		ret = get_sha1_oneline(prefix, sha1, list, oc);
 		free(prefix);
 		return ret;
 	}
 	return 0;
 }
 
-static int get_describe_name(const char *name, int len, unsigned char *sha1)
+static int get_describe_name(const char *name, int len, unsigned char *sha1,
+			     struct object_context *oc)
 {
 	const char *cp;
 
@@ -535,14 +550,15 @@ static int get_describe_name(const char *name, int len, unsigned char *sha1)
 			if (ch == 'g' && cp[-1] == '-') {
 				cp++;
 				len -= cp - name;
-				return get_short_sha1(cp, len, sha1, 1);
+				return get_short_sha1(cp, len, sha1, 1, oc);
 			}
 		}
 	}
 	return -1;
 }
 
-static int get_sha1_1(const char *name, int len, unsigned char *sha1)
+static int get_sha1_1(const char *name, int len, unsigned char *sha1,
+		      struct object_context *oc)
 {
 	int ret, has_suffix;
 	const char *cp;
@@ -569,25 +585,25 @@ static int get_sha1_1(const char *name, int len, unsigned char *sha1)
 		if (!num && len1 == len - 1)
 			num = 1;
 		if (has_suffix == '^')
-			return get_parent(name, len1, sha1, num);
+			return get_parent(name, len1, sha1, num, oc);
 		/* else if (has_suffix == '~') -- goes without saying */
-		return get_nth_ancestor(name, len1, sha1, num);
+		return get_nth_ancestor(name, len1, sha1, num, oc);
 	}
 
-	ret = peel_onion(name, len, sha1);
+	ret = peel_onion(name, len, sha1, oc);
 	if (!ret)
 		return 0;
 
-	ret = get_sha1_basic(name, len, sha1);
+	ret = get_sha1_basic(name, len, sha1, oc);
 	if (!ret)
 		return 0;
 
 	/* It could be describe output that is "SOMETHING-gXXXX" */
-	ret = get_describe_name(name, len, sha1);
+	ret = get_describe_name(name, len, sha1, oc);
 	if (!ret)
 		return 0;
 
-	return get_short_sha1(name, len, sha1, 0);
+	return get_short_sha1(name, len, sha1, 0, oc);
 }
 
 /*
@@ -619,7 +635,8 @@ static int handle_one_ref(const char *path,
 }
 
 static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
-			    struct commit_list *list)
+			    struct commit_list *list,
+			    struct object_context *oc)
 {
 	struct commit_list *backup = NULL, *l;
 	int found = 0;
@@ -672,6 +689,7 @@ static int get_sha1_oneline(const char *prefix, unsigned char *sha1,
 	for (l = backup; l; l = l->next)
 		clear_commit_marks(l->item, ONELINE_SEEN);
 	free_commit_list(backup);
+	oc->used_oneline = found;
 	return found ? 0 : -1;
 }
 
@@ -1029,7 +1047,7 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
 
 	memset(oc, 0, sizeof(*oc));
 	oc->mode = S_IFINVALID;
-	ret = get_sha1_1(name, namelen, sha1);
+	ret = get_sha1_1(name, namelen, sha1, oc);
 	if (!ret)
 		return ret;
 	/* sha1:path --> object name of path in ent sha1
@@ -1046,7 +1064,7 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
 		if (!only_to_die && namelen > 2 && name[1] == '/') {
 			struct commit_list *list = NULL;
 			for_each_ref(handle_one_ref, &list);
-			return get_sha1_oneline(name + 2, sha1, list);
+			return get_sha1_oneline(name + 2, sha1, list, oc);
 		}
 		if (namelen < 3 ||
 		    name[2] != ':' ||
@@ -1081,6 +1099,7 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
 			if (ce_stage(ce) == stage) {
 				hashcpy(sha1, ce->sha1);
 				oc->mode = ce->ce_mode;
+				oc->used_index = 1;
 				free(new_path);
 				return 0;
 			}
@@ -1107,7 +1126,7 @@ int get_sha1_with_context_1(const char *name, unsigned char *sha1,
 			strncpy(object_name, name, cp-name);
 			object_name[cp-name] = '\0';
 		}
-		if (!get_sha1_1(name, cp-name, tree_sha1)) {
+		if (!get_sha1_1(name, cp-name, tree_sha1, oc)) {
 			const char *filename = cp+1;
 			char *new_filename = NULL;
 
-- 
1.7.9.rc0.33.gd3c17

  reply	other threads:[~2012-01-11 19:42 UTC|newest]

Thread overview: 30+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-01-10 21:18 [BUG] git archive broken in 1.7.8.1 Albert Astals Cid
2012-01-10 21:33 ` Carlos Martín Nieto
2012-01-10 22:05   ` Albert Astals Cid
2012-01-10 22:50     ` Carlos Martín Nieto
2012-01-10 23:21       ` Jeff King
2012-01-11 12:12         ` [PATCH] archive: re-allow HEAD:Documentation on a remote invocation Carlos Martín Nieto
2012-01-11 19:39           ` Jeff King
2012-01-11 19:42             ` Jeff King [this message]
2012-01-12  2:36               ` [PATCH 1/2] get_sha1_with_context: report features used in resolution Junio C Hamano
2012-01-12  2:51                 ` Jeff King
2012-01-11 19:42             ` [PATCH 2/2] archive: loosen restrictions on remote object lookup Jeff King
2013-05-29 12:05               ` Ian Harvey
2013-06-05 16:38                 ` Jeff King
2013-06-05 22:35                   ` [RFC/PATCH 0/4] real reachability checks for upload-archive Jeff King
2013-06-05 22:37                     ` [PATCH 1/4] clear parsed flag when we free tree buffers Jeff King
2013-06-06 17:55                       ` Junio C Hamano
2013-06-05 22:39                     ` [PATCH 2/4] upload-archive: restrict remote objects with reachability check Jeff King
2013-06-05 22:40                     ` [PATCH 3/4] list-objects: optimize "revs->blob_objects = 0" case Jeff King
2013-06-05 22:40                     ` [PATCH 4/4] archive: ignore blob objects when checking reachability Jeff King
2013-06-06  7:57                       ` Michael Haggerty
2013-06-07  0:50                       ` Eric Sunshine
2013-06-06 17:27                     ` [RFC/PATCH 0/4] real reachability checks for upload-archive Junio C Hamano
2012-01-12  2:46           ` [PATCH] archive: re-allow HEAD:Documentation on a remote invocation Junio C Hamano
2012-01-12  2:54             ` Jeff King
2012-01-12  2:59               ` Jeff King
2012-01-12  3:03               ` Junio C Hamano
2012-01-12  3:10                 ` Jeff King
2012-01-12  3:20                   ` Junio C Hamano
2012-01-10 23:01     ` [BUG] git archive broken in 1.7.8.1 Allan Wind
2012-01-11 12:51       ` Carlos Martín Nieto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20120111194210.GA12441@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=aacid@kde.org \
    --cc=cmn@elego.de \
    --cc=git@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).