Ejemplo n.º 1
0
Archivo: notes.c Proyecto: Noffica/git
static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
		struct int_node *node, unsigned int n)
{
	struct object_id object_oid;
	size_t prefix_len;
	void *buf;
	struct tree_desc desc;
	struct name_entry entry;

	buf = fill_tree_descriptor(&desc, &subtree->val_oid);
	if (!buf)
		die("Could not read %s for notes-index",
		     oid_to_hex(&subtree->val_oid));

	prefix_len = subtree->key_oid.hash[KEY_INDEX];
	if (prefix_len >= GIT_SHA1_RAWSZ)
		BUG("prefix_len (%"PRIuMAX") is out of range", (uintmax_t)prefix_len);
	if (prefix_len * 2 < n)
		BUG("prefix_len (%"PRIuMAX") is too small", (uintmax_t)prefix_len);
	memcpy(object_oid.hash, subtree->key_oid.hash, prefix_len);
	while (tree_entry(&desc, &entry)) {
		unsigned char type;
		struct leaf_node *l;
		size_t path_len = strlen(entry.path);

		if (path_len == 2 * (GIT_SHA1_RAWSZ - prefix_len)) {
			/* This is potentially the remainder of the SHA-1 */

			if (!S_ISREG(entry.mode))
				/* notes must be blobs */
				goto handle_non_note;

			if (hex_to_bytes(object_oid.hash + prefix_len, entry.path,
					 GIT_SHA1_RAWSZ - prefix_len))
				goto handle_non_note; /* entry.path is not a SHA1 */

			type = PTR_TYPE_NOTE;
		} else if (path_len == 2) {
			/* This is potentially an internal node */
			size_t len = prefix_len;

			if (!S_ISDIR(entry.mode))
				/* internal nodes must be trees */
				goto handle_non_note;

			if (hex_to_bytes(object_oid.hash + len++, entry.path, 1))
				goto handle_non_note; /* entry.path is not a SHA1 */

			/*
			 * Pad the rest of the SHA-1 with zeros,
			 * except for the last byte, where we write
			 * the length:
			 */
			memset(object_oid.hash + len, 0, GIT_SHA1_RAWSZ - len - 1);
			object_oid.hash[KEY_INDEX] = (unsigned char)len;

			type = PTR_TYPE_SUBTREE;
		} else {
			/* This can't be part of a note */
			goto handle_non_note;
		}

		l = xcalloc(1, sizeof(*l));
		oidcpy(&l->key_oid, &object_oid);
		oidcpy(&l->val_oid, &entry.oid);
		if (note_tree_insert(t, node, n, l, type,
				     combine_notes_concatenate))
			die("Failed to load %s %s into notes tree "
			    "from %s",
			    type == PTR_TYPE_NOTE ? "note" : "subtree",
			    oid_to_hex(&l->key_oid), t->ref);

		continue;

handle_non_note:
		/*
		 * Determine full path for this non-note entry. The
		 * filename is already found in entry.path, but the
		 * directory part of the path must be deduced from the
		 * subtree containing this entry based on our
		 * knowledge that the overall notes tree follows a
		 * strict byte-based progressive fanout structure
		 * (i.e. using 2/38, 2/2/36, etc. fanouts).
		 */
		{
			struct strbuf non_note_path = STRBUF_INIT;
			const char *q = oid_to_hex(&subtree->key_oid);
			size_t i;
			for (i = 0; i < prefix_len; i++) {
				strbuf_addch(&non_note_path, *q++);
				strbuf_addch(&non_note_path, *q++);
				strbuf_addch(&non_note_path, '/');
			}
			strbuf_addstr(&non_note_path, entry.path);
			add_non_note(t, strbuf_detach(&non_note_path, NULL),
				     entry.mode, entry.oid.hash);
		}
	}
	free(buf);
}
Ejemplo n.º 2
0
Archivo: notes.c Proyecto: sanj/git
static void load_subtree(struct notes_tree *t, struct leaf_node *subtree,
		struct int_node *node, unsigned int n)
{
	unsigned char object_sha1[20];
	unsigned int prefix_len;
	void *buf;
	struct tree_desc desc;
	struct name_entry entry;
	int len, path_len;
	unsigned char type;
	struct leaf_node *l;

	buf = fill_tree_descriptor(&desc, subtree->val_sha1);
	if (!buf)
		die("Could not read %s for notes-index",
		     sha1_to_hex(subtree->val_sha1));

	prefix_len = subtree->key_sha1[19];
	assert(prefix_len * 2 >= n);
	memcpy(object_sha1, subtree->key_sha1, prefix_len);
	while (tree_entry(&desc, &entry)) {
		path_len = strlen(entry.path);
		len = get_sha1_hex_segment(entry.path, path_len,
				object_sha1 + prefix_len, 20 - prefix_len);
		if (len < 0)
			goto handle_non_note; /* entry.path is not a SHA1 */
		len += prefix_len;

		/*
		 * If object SHA1 is complete (len == 20), assume note object
		 * If object SHA1 is incomplete (len < 20), and current
		 * component consists of 2 hex chars, assume note subtree
		 */
		if (len <= 20) {
			type = PTR_TYPE_NOTE;
			l = (struct leaf_node *)
				xcalloc(sizeof(struct leaf_node), 1);
			hashcpy(l->key_sha1, object_sha1);
			hashcpy(l->val_sha1, entry.sha1);
			if (len < 20) {
				if (!S_ISDIR(entry.mode) || path_len != 2)
					goto handle_non_note; /* not subtree */
				l->key_sha1[19] = (unsigned char) len;
				type = PTR_TYPE_SUBTREE;
			}
			note_tree_insert(t, node, n, l, type,
					 combine_notes_concatenate);
		}
		continue;

handle_non_note:
		/*
		 * Determine full path for this non-note entry:
		 * The filename is already found in entry.path, but the
		 * directory part of the path must be deduced from the subtree
		 * containing this entry. We assume here that the overall notes
		 * tree follows a strict byte-based progressive fanout
		 * structure (i.e. using 2/38, 2/2/36, etc. fanouts, and not
		 * e.g. 4/36 fanout). This means that if a non-note is found at
		 * path "dead/beef", the following code will register it as
		 * being found on "de/ad/beef".
		 * On the other hand, if you use such non-obvious non-note
		 * paths in the middle of a notes tree, you deserve what's
		 * coming to you ;). Note that for non-notes that are not
		 * SHA1-like at the top level, there will be no problems.
		 *
		 * To conclude, it is strongly advised to make sure non-notes
		 * have at least one non-hex character in the top-level path
		 * component.
		 */
		{
			char non_note_path[PATH_MAX];
			char *p = non_note_path;
			const char *q = sha1_to_hex(subtree->key_sha1);
			int i;
			for (i = 0; i < prefix_len; i++) {
				*p++ = *q++;
				*p++ = *q++;
				*p++ = '/';
			}
			strcpy(p, entry.path);
			add_non_note(t, non_note_path, entry.mode, entry.sha1);
		}
	}
	free(buf);
}