diff --git a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF index 9dc6aea16..bc9205c7c 100644 --- a/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF +++ b/org.eclipse.jgit.pgm/META-INF/MANIFEST.MF @@ -19,6 +19,7 @@ Import-Package: org.apache.commons.compress.archivers;version="[1.3,2.0)", org.eclipse.jgit.dircache;version="[4.2.0,4.3.0)", org.eclipse.jgit.errors;version="[4.2.0,4.3.0)", org.eclipse.jgit.gitrepo;version="[4.2.0,4.3.0)", + org.eclipse.jgit.internal.ketch;version="[4.2.0,4.3.0)", org.eclipse.jgit.internal.storage.file;version="[4.2.0,4.3.0)", org.eclipse.jgit.internal.storage.pack;version="[4.2.0,4.3.0)", org.eclipse.jgit.internal.storage.reftree;version="[4.2.0,4.3.0)", diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java index 04182d6db..03f3fac0b 100644 --- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java +++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java @@ -45,18 +45,29 @@ package org.eclipse.jgit.pgm; import java.io.File; import java.net.InetSocketAddress; +import java.net.URISyntaxException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.List; import java.util.concurrent.Executors; +import org.eclipse.jgit.internal.ketch.KetchLeader; +import org.eclipse.jgit.internal.ketch.KetchLeaderCache; +import org.eclipse.jgit.internal.ketch.KetchPreReceive; +import org.eclipse.jgit.internal.ketch.KetchSystem; +import org.eclipse.jgit.internal.ketch.KetchText; +import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.pgm.internal.CLIText; import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.storage.file.WindowCacheConfig; import org.eclipse.jgit.storage.pack.PackConfig; import org.eclipse.jgit.transport.DaemonClient; import org.eclipse.jgit.transport.DaemonService; +import org.eclipse.jgit.transport.ReceivePack; import org.eclipse.jgit.transport.resolver.FileResolver; +import org.eclipse.jgit.transport.resolver.ReceivePackFactory; +import org.eclipse.jgit.transport.resolver.ServiceNotAuthorizedException; +import org.eclipse.jgit.transport.resolver.ServiceNotEnabledException; import org.eclipse.jgit.util.FS; import org.kohsuke.args4j.Argument; import org.kohsuke.args4j.Option; @@ -90,6 +101,13 @@ class Daemon extends TextBuiltin { @Option(name = "--export-all", usage = "usage_exportWithoutGitDaemonExportOk") boolean exportAll; + @Option(name = "--ketch") + KetchServerType ketchServerType; + + enum KetchServerType { + LEADER; + } + @Argument(required = true, metaVar = "metaVar_directory", usage = "usage_directoriesToExport") final List directory = new ArrayList(); @@ -146,7 +164,9 @@ class Daemon extends TextBuiltin { service(d, n).setOverridable(true); for (final String n : forbidOverride) service(d, n).setOverridable(false); - + if (ketchServerType == KetchServerType.LEADER) { + startKetchLeader(d); + } d.start(); outw.println(MessageFormat.format(CLIText.get().listeningOn, d.getAddress())); } @@ -159,4 +179,29 @@ class Daemon extends TextBuiltin { throw die(MessageFormat.format(CLIText.get().serviceNotSupported, n)); return svc; } + + private void startKetchLeader(org.eclipse.jgit.transport.Daemon daemon) { + KetchSystem system = new KetchSystem(); + final KetchLeaderCache leaders = new KetchLeaderCache(system); + final ReceivePackFactory factory; + + factory = daemon.getReceivePackFactory(); + daemon.setReceivePackFactory(new ReceivePackFactory() { + @Override + public ReceivePack create(DaemonClient req, Repository repo) + throws ServiceNotEnabledException, + ServiceNotAuthorizedException { + ReceivePack rp = factory.create(req, repo); + KetchLeader leader; + try { + leader = leaders.get(repo); + } catch (URISyntaxException err) { + throw new ServiceNotEnabledException( + KetchText.get().invalidFollowerUri, err); + } + rp.setPreReceiveHook(new KetchPreReceive(leader)); + return rp; + } + }); + } } \ No newline at end of file diff --git a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties index 3817fb93c..1fbb7cb3b 100644 --- a/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties +++ b/org.eclipse.jgit/resources/org/eclipse/jgit/internal/ketch/KetchText.properties @@ -1,6 +1,7 @@ accepted=accepted. cannotFetchFromLocalReplica=cannot fetch from LocalReplica failed=failed! +invalidFollowerUri=invalid follower URI leaderFailedToStore=leader failed to store localReplicaRequired=LocalReplica instance is required mismatchedTxnNamespace=mismatched txnNamespace; expected {0} found {1} diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java index da85c0112..b6c3bc92c 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/internal/ketch/KetchText.java @@ -57,6 +57,7 @@ public class KetchText extends TranslationBundle { /***/ public String accepted; /***/ public String cannotFetchFromLocalReplica; /***/ public String failed; + /***/ public String invalidFollowerUri; /***/ public String leaderFailedToStore; /***/ public String localReplicaRequired; /***/ public String mismatchedTxnNamespace; diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java index d9e0b937e..2593ba556 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/transport/Daemon.java @@ -255,6 +255,16 @@ public class Daemon { uploadPackFactory = (UploadPackFactory) UploadPackFactory.DISABLED; } + /** + * Get the factory used to construct per-request ReceivePack. + * + * @return the factory. + * @since 4.2 + */ + public ReceivePackFactory getReceivePackFactory() { + return receivePackFactory; + } + /** * Set the factory to construct and configure per-request ReceivePack. *