Support replication to local folder
Allow to specify a local folder for 'remote.<name>.url' in
'replication.config' so that the git repositories are replicated to
this local folder.
Replicating to a local folder makes e.g. sense if a network share is
mounted to which the repositories should be replicated for backup
purposes.
Change-Id: I4fb5af8efcb9ab3798707f1403cd1231854e10bc
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/Documentation/config-replication.txt b/Documentation/config-replication.txt
index 787a9be..772282e 100644
--- a/Documentation/config-replication.txt
+++ b/Documentation/config-replication.txt
@@ -14,7 +14,10 @@
public/private key pair. On a trusted network it is also possible to
use replication over the insecure (but much faster) git:// protocol,
by enabling the `receive-pack` service on the receiving system, but
-this configuration is not recommended.
+this configuration is not recommended. It is also possible to
+specify a local path as replication target. This makes e.g. sense if
+a network share is mounted to which the repositories should be
+replicated.
Enabling Replication
--------------------
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
index d359a67..154c609 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/PushReplication.java
@@ -39,8 +39,10 @@
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.storage.file.FileBasedConfig;
+import org.eclipse.jgit.storage.file.FileRepository;
import org.eclipse.jgit.transport.JschConfigSessionFactory;
import org.eclipse.jgit.transport.OpenSshConfig;
import org.eclipse.jgit.transport.RefSpec;
@@ -270,16 +272,43 @@
}
private void replicateProject(final URIish replicateURI, final String head) {
+ if (!replicateURI.isRemote()) {
+ replicateProjectLocally(replicateURI, head);
+ } else if (usingSSH(replicateURI)) {
+ replicateProjectOverSsh(replicateURI, head);
+ } else {
+ log.warn("Cannot create new project on remote site since neither the "
+ + "connection method is SSH nor the replication target is local: "
+ + replicateURI.toString());
+ return;
+ }
+ }
+
+ private void replicateProjectLocally(final URIish replicateURI,
+ final String head) {
+ try {
+ final Repository repo = new FileRepository(replicateURI.getPath());
+ try {
+ repo.create(true /* bare */);
+
+ final RefUpdate u = repo.updateRef(Constants.HEAD);
+ u.disableRefLog();
+ u.link(head);
+ } finally {
+ repo.close();
+ }
+ } catch (IOException e) {
+ log.error("Failed to replicate project locally: "
+ + replicateURI.getPath());
+ }
+ }
+
+ private void replicateProjectOverSsh(final URIish replicateURI,
+ final String head) {
SshSessionFactory sshFactory = SshSessionFactory.getInstance();
RemoteSession sshSession;
String projectPath = QuotedString.BOURNE.quote(replicateURI.getPath());
- if (!usingSSH(replicateURI)) {
- log.warn("Cannot create new project on remote site since the connection "
- + "method is not SSH: " + replicateURI.toString());
- return;
- }
-
OutputStream errStream = createErrStream();
String cmd =
"mkdir -p " + projectPath + "&& cd " + projectPath