git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH 03/23] pack v4: scan tree objects

From
Nicolas Pitre <nico@fluxnic.net>
Date
Aug 27, 2013, 04:25 UTC
Message-ID
<1377577567-27655-4-git-send-email-nico@fluxnic.net>
In-Reply-To
<1377577567-27655-1-git-send-email-nico@fluxnic.net>
From: Nicolas Pitre <nico@lenovo.(none)>

Let's read a pack to feed our dictionary with all the path strings contained in all the tree objects.

Dump the resulting dictionary sorted by frequency to stdout.
Signed-off-by: Nicolas Pitre <nico@fluxnic.net>
---
 Makefile        |   1 +
 packv4-create.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 138 insertions(+)
diff --git a/Makefile b/Makefile
index 3588ca1..4716113 100644
--- a/Makefile
+++ b/Makefile
@@ -550,6 +550,7 @@ PROGRAM_OBJS += shell.o
 PROGRAM_OBJS += show-index.o
 PROGRAM_OBJS += upload-pack.o
 PROGRAM_OBJS += remote-testsvn.o
+PROGRAM_OBJS += packv4-create.o
 
 # Binary suffix, set to .exe for Windows builds
 X =
diff --git a/packv4-create.c b/packv4-create.c
index 2de6d41..00762a5 100644
--- a/packv4-create.c
+++ b/packv4-create.c
@@ -9,6 +9,8 @@
  */
 
 #include "cache.h"
+#include "object.h"
+#include "tree-walk.h"
 
 struct data_entry {
 	unsigned offset;
@@ -125,6 +127,22 @@ static void sort_dict_entries_by_hits(struct dict_table *t)
 	rehash_entries(t);
 }
 
+static struct dict_table *tree_path_table;
+
+static int add_tree_dict_entries(void *buf, unsigned long size)
+{
+	struct tree_desc desc;
+	struct name_entry name_entry;
+
+	if (!tree_path_table)
+		tree_path_table = create_dict_table();
+
+	init_tree_desc(&desc, buf, size);
+	while (tree_entry(&desc, &name_entry))
+		dict_add_entry(tree_path_table, name_entry.path);
+	return 0;
+}
+
 void dict_dump(struct dict_table *t)
 {
 	int i;
@@ -135,3 +153,122 @@ void dict_dump(struct dict_table *t)
 			t->entry[i].hits,
 			t->data + t->entry[i].offset);
 }
+
+struct idx_entry
+{
+	off_t                offset;
+	const unsigned char *sha1;
+};
+
+static int sort_by_offset(const void *e1, const void *e2)
+{
+	const struct idx_entry *entry1 = e1;
+	const struct idx_entry *entry2 = e2;
+	if (entry1->offset < entry2->offset)
+		return -1;
+	if (entry1->offset > entry2->offset)
+		return 1;
+	return 0;
+}
+static int create_pack_dictionaries(struct packed_git *p)
+{
+	uint32_t nr_objects, i;
+	struct idx_entry *objects;
+
+	nr_objects = p->num_objects;
+	objects = xmalloc((nr_objects + 1) * sizeof(*objects));
+	objects[nr_objects].offset = p->index_size - 40;
+	for (i = 0; i < nr_objects; i++) {
+		objects[i].sha1 = nth_packed_object_sha1(p, i);
+		objects[i].offset = nth_packed_object_offset(p, i);
+	}
+	qsort(objects, nr_objects, sizeof(*objects), sort_by_offset);
+
+	for (i = 0; i < nr_objects; i++) {
+		void *data;
+		enum object_type type;
+		unsigned long size;
+		struct object_info oi = {};
+
+		oi.typep = &type;
+		oi.sizep = &size;
+		if (packed_object_info(p, objects[i].offset, &oi) < 0)
+			die("cannot get type of %s from %s",
+			    sha1_to_hex(objects[i].sha1), p->pack_name);
+
+		switch (type) {
+		case OBJ_TREE:
+			break;
+		default:
+			continue;
+		}
+		data = unpack_entry(p, objects[i].offset, &type, &size);
+		if (!data)
+			die("cannot unpack %s from %s",
+			    sha1_to_hex(objects[i].sha1), p->pack_name);
+		if (check_sha1_signature(objects[i].sha1, data, size, typename(type)))
+			die("packed %s from %s is corrupt",
+			    sha1_to_hex(objects[i].sha1), p->pack_name);
+		if (add_tree_dict_entries(data, size) < 0)
+			die("can't process %s object %s",
+				typename(type), sha1_to_hex(objects[i].sha1));
+		free(data);
+	}
+	free(objects);
+
+	return 0;
+}
+
+static int process_one_pack(const char *path)
+{
+	char arg[PATH_MAX];
+	int len;
+	struct packed_git *p;
+
+	len = strlcpy(arg, path, PATH_MAX);
+	if (len >= PATH_MAX)
+		return error("name too long: %s", path);
+
+	/*
+	 * In addition to "foo.idx" we accept "foo.pack" and "foo";
+	 * normalize these forms to "foo.idx" for add_packed_git().
+	 */
+	if (has_extension(arg, ".pack")) {
+		strcpy(arg + len - 5, ".idx");
+		len--;
+	} else if (!has_extension(arg, ".idx")) {
+		if (len + 4 >= PATH_MAX)
+			return error("name too long: %s.idx", arg);
+		strcpy(arg + len, ".idx");
+		len += 4;
+	}
+
+	/*
+	 * add_packed_git() uses our buffer (containing "foo.idx") to
+	 * build the pack filename ("foo.pack").  Make sure it fits.
+	 */
+	if (len + 1 >= PATH_MAX) {
+		arg[len - 4] = '\0';
+		return error("name too long: %s.pack", arg);
+	}
+
+	p = add_packed_git(arg, len, 1);
+	if (!p)
+		return error("packfile %s not found.", arg);
+
+	install_packed_git(p);
+	if (open_pack_index(p))
+		return error("packfile %s index not opened", p->pack_name);
+	return create_pack_dictionaries(p);
+}
+
+int main(int argc, char *argv[])
+{
+	if (argc != 2) {
+		fprintf(stderr, "Usage: %s <packfile>\n", argv[0]);
+		exit(1);
+	}
+	process_one_pack(argv[1]);
+	dict_dump(tree_path_table);
+	return 0;
+}
-- 
1.8.4.22.g54757b7
Previous: Nicolas PitreNext: Nicolas Pitre
Message 6 of 83 in “Preliminary pack v4 support”
  1. 00/23 Preliminary pack v4 supportNicolas Pitre, Aug 27, 2013
  2. 01/23 pack v4: initial pack dictionary structure and codeNicolas Pitre, Aug 27, 2013
  3. Junio C HamanoAug 27, 2013
  4. Nicolas PitreAug 27, 2013
  5. 02/23 export packed_object_info()Nicolas Pitre, Aug 27, 2013
  6. 03/23 pack v4: scan tree objectsNicolas Pitre, Aug 27, 2013
  7. 04/23 pack v4: add tree entry mode support to dictionary entriesNicolas Pitre, Aug 27, 2013
  8. 05/23 pack v4: add commit object parsingNicolas Pitre, Aug 27, 2013
  9. Junio C HamanoAug 27, 2013
  10. Nicolas PitreAug 27, 2013
  11. Junio C HamanoAug 27, 2013
  12. 06/23 pack v4: split the object list and dictionary creationNicolas Pitre, Aug 27, 2013
  13. 07/23 pack v4: move to struct pack_idx_entry and get rid of our own struct idx_entryNicolas Pitre, Aug 27, 2013
  14. 08/23 pack v4: basic references encodingNicolas Pitre, Aug 27, 2013
  15. Junio C HamanoAug 27, 2013
  16. Nicolas PitreAug 27, 2013
  17. 09/23 pack v4: commit object encodingNicolas Pitre, Aug 27, 2013
  18. Junio C HamanoAug 27, 2013
  19. Nicolas PitreAug 27, 2013
  20. Nicolas PitreAug 27, 2013
  21. Junio C HamanoAug 27, 2013
  22. Nicolas PitreAug 27, 2013
  23. Duy NguyenSep 2, 2013
  24. Nicolas PitreSep 3, 2013
  25. Duy NguyenSep 3, 2013
  26. Nicolas PitreSep 5, 2013
  27. 10/23 pack v4: tree object encodingNicolas Pitre, Aug 27, 2013
  28. Junio C HamanoAug 27, 2013
  29. Nicolas PitreAug 27, 2013
  30. 11/23 pack v4: dictionary table outputNicolas Pitre, Aug 27, 2013
  31. 12/23 pack v4: creation codeNicolas Pitre, Aug 27, 2013
  32. Junio C HamanoAug 27, 2013
  33. Nicolas PitreAug 27, 2013
  34. 13/23 pack v4: object headersNicolas Pitre, Aug 27, 2013
  35. 14/23 pack v4: object data copyNicolas Pitre, Aug 27, 2013
  36. Junio C HamanoAug 27, 2013
  37. Nicolas PitreAug 27, 2013
  38. 15/23 pack v4: object writingNicolas Pitre, Aug 27, 2013
  39. 16/23 pack v4: tree object delta encodingNicolas Pitre, Aug 27, 2013
  40. 17/23 pack v4: load delta candidate for encoding tree objectsNicolas Pitre, Aug 27, 2013
  41. 18/23 pack v4: honor pack.compression config optionNicolas Pitre, Aug 27, 2013
  42. 19/23 pack v4: relax commit parsing a bitNicolas Pitre, Aug 27, 2013
  43. 20/23 pack index v3Nicolas Pitre, Aug 27, 2013
  44. 21/23 pack v4: normalize pack name to properly generate the pack index file nameNicolas Pitre, Aug 27, 2013
  45. 22/23 pack v4: add progress displayNicolas Pitre, Aug 27, 2013
  46. 23/23 initial pack index v3 support on the read sideNicolas Pitre, Aug 27, 2013
  47. Duy NguyenAug 31, 2013
  48. Nicolas PitreSep 3, 2013
  49. Duy NguyenSep 3, 2013
  50. Document pack v4 formatNguyễn Thái Ngọc Duy, Aug 27, 2013
  51. Junio C HamanoAug 27, 2013
  52. Nicolas PitreAug 27, 2013
  53. Document pack v4 formatNguyễn Thái Ngọc Duy, Aug 31, 2013
  54. Nicolas PitreSep 3, 2013
  55. Nicolas PitreSep 3, 2013
  56. Duy NguyenSep 3, 2013
  57. Duy NguyenSep 3, 2013
  58. Nicolas PitreSep 5, 2013
  59. Duy NguyenSep 5, 2013
  60. Nicolas PitreSep 5, 2013
  61. Duy NguyenSep 5, 2013
  62. Nicolas PitreSep 5, 2013
  63. Duy NguyenSep 5, 2013
  64. Nicolas PitreSep 5, 2013
  65. Junio C HamanoSep 5, 2013
  66. Nicolas PitreSep 5, 2013
  67. Duy NguyenSep 6, 2013
  68. Nicolas PitreSep 6, 2013
  69. Document pack v4 formatNguyễn Thái Ngọc Duy, Sep 6, 2013
  70. Nicolas PitreSep 6, 2013
  71. Duy NguyenSep 6, 2013
  72. Nicolas PitreSep 6, 2013
  73. Duy NguyenSep 6, 2013
  74. Nicolas PitreSep 6, 2013
  75. Nicolas PitreSep 7, 2013
  76. Nicolas PitreSep 7, 2013
  77. Duy NguyenSep 7, 2013
  78. Junio C HamanoAug 27, 2013
  79. Nicolas PitreAug 27, 2013
  80. Junio C HamanoAug 27, 2013
  81. Duy NguyenAug 28, 2013
  82. Nicolas PitreAug 28, 2013
  83. Duy NguyenAug 28, 2013

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.