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@xxxxxxxxxxx> --- .../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 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html