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

[PATCH] Implement packed refs

From
Robin Rosenberg <robin.rosenberg@dewire.com>
Date
May 13, 2007, 23:39 UTC
Message-ID
<11790995571637-git-send-email-robin.rosenberg@dewire.com>
In-Reply-To
<11790995573817-git-send-email-robin.rosenberg@dewire.com>
Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com>
---
 .../src/org/spearce/jgit/lib/Repository.java       |   48 +++++++++++++++++++-
 .../tst/org/spearce/jgit/lib/T0003_Basic.java      |   44 ++++++++++++++++++
 2 files changed, 91 insertions(+), 1 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
index 76191be..3b2a82c 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/lib/Repository.java
@@ -399,6 +399,7 @@ public class Repository {
 
 	private Ref readRef(final String revstr, final boolean missingOk)
 			throws IOException {
+		refreshPackredRefsCache();
 		for (int k = 0; k < refSearchPaths.length; k++) {
 			final Ref r = readRefBasic(refSearchPaths[k] + revstr);
 			if (missingOk || r.getObjectId() != null) {
@@ -411,6 +412,10 @@ public class Repository {
 	private Ref readRefBasic(String name) throws IOException {
 		int depth = 0;
 		REF_READING: do {
+			ObjectId id = packedRefs.get(name);
+			if (id != null)
+				return new Ref(null, id);
+
 			final File f = new File(getDirectory(), name);
 			if (!f.isFile()) {
 				return new Ref(f, null);
@@ -470,7 +475,43 @@ public class Repository {
 	}
 
 	public Collection<String> getTags() {
-		return listFilesRecursively(new File(refsDir, "tags"), null);
+		Collection<String> tags = listFilesRecursively(new File(refsDir, "tags"), null);
+		refreshPackredRefsCache();
+		tags.addAll(packedRefs.keySet());
+		return tags;
+	}
+
+	private Map<String,ObjectId> packedRefs = new HashMap<String,ObjectId>();
+	private long packedrefstime = 0;
+
+	private void refreshPackredRefsCache() {
+		File file = new File(gitDir, "packed-refs");
+		if (!file.exists()) {
+			if (packedRefs.size() > 0)
+				packedRefs = new HashMap();
+			return;
+		}
+		if (file.lastModified() == packedrefstime)
+			return;
+		Map newPackedRefs = new HashMap();
+		try {
+			BufferedReader b=new BufferedReader(new FileReader(file));
+			String p;
+			while ((p = b.readLine()) != null) {
+				if (p.charAt(0) == '#')
+					continue;
+				if (p.charAt(0) == '^') {
+					continue;
+				}
+				int spos = p.indexOf(' ');
+				ObjectId id = new ObjectId(p.substring(0,spos));
+				String name = p.substring(spos+1);
+				newPackedRefs.put(name, id);
+			}
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+		packedRefs = newPackedRefs;
 	}
 
 	/**
@@ -551,4 +592,9 @@ public class Repository {
 		}
 		return ret;
 	}
+	
+	/** Clean up stale caches */
+	public void refreshFromDisk() {
+		packedRefs = null;
+	}
 }
diff --git a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0003_Basic.java b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0003_Basic.java
index 2f76907..02ecabf 100644
--- a/org.spearce.jgit/tst/org/spearce/jgit/lib/T0003_Basic.java
+++ b/org.spearce.jgit/tst/org/spearce/jgit/lib/T0003_Basic.java
@@ -21,6 +21,7 @@ import java.io.FileInputStream;
 import java.io.FileReader;
 import java.io.FileWriter;
 import java.io.IOException;
+import java.io.PrintWriter;
 
 public class T0003_Basic extends RepositoryTestCase {
 	public void test001_Initalize() {
@@ -428,4 +429,47 @@ public class T0003_Basic extends RepositoryTestCase {
 		ObjectId cid = new ObjectWriter(db).writeCommit(commit);
 		assertEquals("2979b39d385014b33287054b87f77bcb3ecb5ebf", cid.toString());
 	}
+	
+	public void test025_packedRefs() throws IOException {
+		test020_createBlobTag();
+		test021_createTreeTag();
+		test022_createCommitTag();
+
+		if (!new File(db.getDirectory(),"refs/tags/test020").delete()) throw new Error("Cannot delete unpacked tag");
+		if (!new File(db.getDirectory(),"refs/tags/test021").delete()) throw new Error("Cannot delete unpacked tag");
+		if (!new File(db.getDirectory(),"refs/tags/test022").delete()) throw new Error("Cannot delete unpacked tag");
+
+		// We cannot resolve it now, since we have no ref
+		Tag mapTag20missing = db.mapTag("test020");
+		assertNull(mapTag20missing);
+
+		// Construct packed refs file
+		PrintWriter w = new PrintWriter(new FileWriter(new File(db.getDirectory(), "packed-refs")));
+		w.println("# packed-refs with: peeled");
+		w.println("6759556b09fbb4fd8ae5e315134481cc25d46954 refs/tags/test020");
+		w.println("^e69de29bb2d1d6434b8b29ae775ad8c2e48c5391");
+		w.println("b0517bc8dbe2096b419d42424cd7030733f4abe5 refs/tags/test021");
+		w.println("^417c01c8795a35b8e835113a85a5c0c1c77f67fb");
+		w.println("0ce2ebdb36076ef0b38adbe077a07d43b43e3807 refs/tags/test022");
+		w.println("^b5d3b45a96b340441f5abb9080411705c51cc86c");
+		w.close();
+
+		Tag mapTag20 = db.mapTag("test020");
+		assertEquals("blob", mapTag20.getType());
+		assertEquals("test020 tagged\n", mapTag20.getMessage());
+		assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag20.getAuthor());
+		assertEquals("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", mapTag20.getObjId().toString());
+
+		Tag mapTag21 = db.mapTag("test021");
+		assertEquals("tree", mapTag21.getType());
+		assertEquals("test021 tagged\n", mapTag21.getMessage());
+		assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag21.getAuthor());
+		assertEquals("417c01c8795a35b8e835113a85a5c0c1c77f67fb", mapTag21.getObjId().toString());
+
+		Tag mapTag22 = db.mapTag("test022");
+		assertEquals("commit", mapTag22.getType());
+		assertEquals("test022 tagged\n", mapTag22.getMessage());
+		assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag22.getAuthor());
+		assertEquals("b5d3b45a96b340441f5abb9080411705c51cc86c", mapTag22.getObjId().toString());
+	}
 }
-- 
1.5.1.1
Previous: Robin RosenbergNext: Robin Rosenberg
Message 4 of 13 in “This week in EGIT - more tags”
  1. Robin RosenbergMay 13, 2007
  2. Implement simple tagsRobin Rosenberg, May 13, 2007
  3. Write refs when creating tagsRobin Rosenberg, May 13, 2007
  4. Implement packed refsRobin Rosenberg, May 13, 2007
  5. Show tags in history viewRobin Rosenberg, May 13, 2007
  6. Shawn O. PearceMay 14, 2007
  7. Robin RosenbergMay 14, 2007
  8. The first patch in the seriesRobin Rosenberg, May 13, 2007
  9. Require JDK1.5Robin Rosenberg, May 13, 2007
  10. Grzegorz KulewskiMay 14, 2007
  11. Noel GrandinMay 14, 2007
  12. Robin RosenbergMay 14, 2007
  13. Set required execution enviromentRobin Rosenberg, May 14, 2007

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.