Skip to content

Commit

Permalink
Fix symbolic ref handling by the ref database, also set up HEAD symbo…
Browse files Browse the repository at this point in the history
…lic ref on the first repo push
  • Loading branch information
Ignas committed Aug 15, 2024
1 parent 3a67131 commit cf4ef83
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 8 deletions.
19 changes: 19 additions & 0 deletions src/main/java/lt/pow/nukagit/dfs/GitDfsPackCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import org.apache.sshd.common.util.threads.CloseableExecutorService;
import org.apache.sshd.git.pack.GitPackCommand;
import org.eclipse.jgit.internal.storage.dfs.DfsRepository;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.transport.ReceivePack;
import org.eclipse.jgit.transport.RemoteConfig;
Expand Down Expand Up @@ -54,6 +56,23 @@ public void run() {
uploadPack(db);
} else if (RemoteConfig.DEFAULT_RECEIVE_PACK.equals(subCommand)) {
receivePack(db);
// if HEAD ref has not been set up yet, set it up
if (db.getRefDatabase().exactRef(Constants.HEAD) == null) {
List<String> preferredRefs = List.of("main", "master");
boolean headSet = false;
for (String ref : preferredRefs) {
if (db.getRefDatabase().exactRef(Constants.R_HEADS + ref) != null) {
RefUpdate u = db.updateRef(Constants.HEAD);
u.link(Constants.R_HEADS + ref);
headSet = true;
break;
}
}
// If no preferred refs exist, link HEAD to the only ref if there is exactly one
if (!headSet && db.getRefDatabase().getRefs().size() == 1) {
RefUpdate u = db.updateRef(Constants.HEAD);
u.link(db.getRefDatabase().getRefs().get(0).getName());
} }
} else {
throw new IllegalArgumentException("Unknown git command: " + command);
}
Expand Down
8 changes: 5 additions & 3 deletions src/main/java/lt/pow/nukagit/dfs/NukagitDfsRepository.java
Original file line number Diff line number Diff line change
Expand Up @@ -131,14 +131,14 @@ private Ref toJgitRef(HashMap<String, DfsRef> allRefMap, DfsRef dfsRef) {
} else if (dfsRef.isPeeled()) {
if (dfsRef.peeledRef() == null) {
return new ObjectIdRef.PeeledNonTag(
Ref.Storage.LOOSE, dfsRef.name(), ObjectId.fromString(dfsRef.objectID()));
Ref.Storage.PACKED, dfsRef.name(), ObjectId.fromString(dfsRef.objectID()));

}
return new ObjectIdRef.PeeledTag(
Ref.Storage.LOOSE, dfsRef.name(), ObjectId.fromString(dfsRef.objectID()), ObjectId.fromString(dfsRef.peeledRef()));
Ref.Storage.PACKED, dfsRef.name(), ObjectId.fromString(dfsRef.objectID()), ObjectId.fromString(dfsRef.peeledRef()));
}
return new ObjectIdRef.Unpeeled(
Ref.Storage.LOOSE, dfsRef.name(), ObjectId.fromString(dfsRef.objectID()));
Ref.Storage.PACKED, dfsRef.name(), ObjectId.fromString(dfsRef.objectID()));
}

private DfsRef toDfsRef(Ref ref) {
Expand All @@ -147,6 +147,7 @@ private DfsRef toDfsRef(Ref ref) {
.name(ref.getName())
.isSymbolic(true)
.target(ref.getTarget().getName())
.isPeeled(false)
.build();
}
return ImmutableDfsRef.builder()
Expand Down Expand Up @@ -179,6 +180,7 @@ protected RefCache scanAllRefs() throws IOException {

var idRefListBuilder = new RefList.Builder<>();
idRefListBuilder.addAll(idRefList.toArray(new Ref[0]), 0, idRefList.size());
idRefListBuilder.addAll(symRefList.toArray(new Ref[0]), 0, symRefList.size());
idRefListBuilder.sort();
RefList<Ref> ids = idRefListBuilder.toRefList();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,9 +162,7 @@ class NukagitIntegrationTest extends Specification {
.setUri(new URIish("ssh://git@localhost:${sshPort}/${path}"))
.call()
commitRandomFile(git)
git.checkout().setName("main").call()
git.push().setPushAll().call()
// This does not set HEAD, might be a bug in the server
return git
}

Expand All @@ -174,8 +172,6 @@ class NukagitIntegrationTest extends Specification {
CloneCommand cloneCommand = Git.cloneRepository()
cloneCommand.setURI("ssh://git@localhost:${sshPort}/${path}")
cloneCommand.setDirectory(clonePath)
// For now set it to main explicitly, because HEAD does not exist in the remote repository
cloneCommand.setBranch("main")
return cloneCommand.call()
}

Expand Down Expand Up @@ -204,6 +200,8 @@ class NukagitIntegrationTest extends Specification {
commitRandomFile(git)
then:
git.push().call().first().getRemoteUpdates().first().getStatus() == RemoteRefUpdate.Status.OK
// the remote should also get main branch set up as it's HEAD
git.lsRemote().call().find { it.getName() == "HEAD" }.target.name == "refs/heads/main"
}

def "test pushing conflicting changes to main should fail"() {
Expand Down Expand Up @@ -264,7 +262,8 @@ class NukagitIntegrationTest extends Specification {
}

var git = cloneRepository("minio/repo")
git.lsRemote().call().size() == nThreads + 1
// main and HEAD are two extra refs
git.lsRemote().call().size() == nThreads + 2
}

def sshRun(String command) {
Expand Down

0 comments on commit cf4ef83

Please sign in to comment.