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

[JGIT PATCH 3/4] Automatically initialize a new dumb repository during push

From
Shawn O. Pearce <spearce@spearce.org>
Date
Jul 9, 2008, 04:15 UTC
Message-ID
<1215576931-4174-4-git-send-email-spearce@spearce.org>
In-Reply-To
<1215576931-4174-3-git-send-email-spearce@spearce.org>

If we are pushing into a repository which has no refs and no packs we can reasonably assume the repository is brand new. In such cases we must ensure there is a valid HEAD and config file in the repository, otherwise Git clients reading the repository may not be able to recognize its contents correctly.

By default we try to create HEAD from refs/heads/master, if that is among the branches being pushed by the user. This mirrors what git-init would have initialized HEAD to be. However if master was not among the branches pushed then another branch is selected as a reasonable default.

We initialize .git/config to a very bare configuration, listing only the repository version. We avoid setting up core.filemode as we cannot genrally detect if the remote side understands executable mode bits.

Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
---
 .../spearce/jgit/transport/WalkPushConnection.java |   54 ++++++++++++++++++++
 1 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java
index e11b85a..bb5a653 100644
--- a/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java
+++ b/org.spearce.jgit/src/org/spearce/jgit/transport/WalkPushConnection.java
@@ -48,6 +48,7 @@ import java.util.TreeMap;
 
 import org.spearce.jgit.errors.TransportException;
 import org.spearce.jgit.lib.AnyObjectId;
+import org.spearce.jgit.lib.Constants;
 import org.spearce.jgit.lib.ObjectId;
 import org.spearce.jgit.lib.PackWriter;
 import org.spearce.jgit.lib.ProgressMonitor;
@@ -151,6 +152,12 @@ class WalkPushConnection extends BaseConnection implements PushConnection {
 		for (final RemoteRefUpdate u : updates)
 			updateCommand(u);
 
+		// Is this a new repository? If so we should create additional
+		// metadata files so it is properly initialized during the push.
+		//
+		if (!updates.isEmpty() && isNewRepository())
+			createNewRepository(updates);
+
 		if (!packedRefUpdates.isEmpty()) {
 			try {
 				dest.writePackedRefs(newRefs.values());
@@ -307,4 +314,51 @@ class WalkPushConnection extends BaseConnection implements PushConnection {
 			u.setMessage(e.getMessage());
 		}
 	}
+
+	private boolean isNewRepository() {
+		return getRefsMap().isEmpty() && packNames != null
+				&& packNames.isEmpty();
+	}
+
+	private void createNewRepository(final List<RemoteRefUpdate> updates)
+			throws TransportException {
+		try {
+			final String ref = "ref: " + pickHEAD(updates) + "\n";
+			final byte[] bytes = ref.getBytes(Constants.CHARACTER_ENCODING);
+			dest.writeFile("../HEAD", bytes);
+		} catch (IOException e) {
+			throw new TransportException(uri, "cannot create HEAD", e);
+		}
+
+		try {
+			final String config = "[core]\n"
+					+ "\trepositoryformatversion = 0\n";
+			final byte[] bytes = config.getBytes(Constants.CHARACTER_ENCODING);
+			dest.writeFile("../config", bytes);
+		} catch (IOException e) {
+			throw new TransportException(uri, "cannot create config", e);
+		}
+	}
+
+	private static String pickHEAD(final List<RemoteRefUpdate> updates) {
+		// Try to use master if the user is pushing that, it is the
+		// default branch and is likely what they want to remain as
+		// the default on the new remote.
+		//
+		for (final RemoteRefUpdate u : updates) {
+			final String n = u.getRemoteName();
+			if (n.equals(Constants.HEADS_PREFIX + "/" + Constants.MASTER))
+				return n;
+		}
+
+		// Pick any branch, under the assumption the user pushed only
+		// one to the remote side.
+		//
+		for (final RemoteRefUpdate u : updates) {
+			final String n = u.getRemoteName();
+			if (n.startsWith(Constants.HEADS_PREFIX + "/"))
+				return n;
+		}
+		return updates.get(0).getRemoteName();
+	}
 }
-- 
1.5.6.74.g8a5e
Previous: Shawn O. PearceNext: Shawn O. Pearce
Message 4 of 5 in “Misc. push transport fixes”
  1. 0/4 Misc. push transport fixesShawn O. Pearce, Jul 9, 2008
  2. 1/4 Avoid deadlock while fetching from local repositoryShawn O. Pearce, Jul 9, 2008
  3. 2/4 Fix pushing of annotated tags to actually include the tag objectShawn O. Pearce, Jul 9, 2008
  4. 3/4 Automatically initialize a new dumb repository during pushShawn O. Pearce, Jul 9, 2008
  5. 4/4 Use a singleton for the NullProgressMonitor implementationShawn O. Pearce, Jul 9, 2008

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.