1   /*
2    * Copyright 2017 LINE Corporation
3    *
4    * LINE Corporation licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  
17  package com.linecorp.centraldogma.server.internal.mirror;
18  
19  import static com.linecorp.centraldogma.server.mirror.MirrorSchemes.SCHEME_GIT_HTTP;
20  import static com.linecorp.centraldogma.server.mirror.MirrorSchemes.SCHEME_GIT_HTTPS;
21  
22  import java.io.File;
23  import java.net.URI;
24  import java.util.function.Consumer;
25  
26  import javax.annotation.Nullable;
27  
28  import org.eclipse.jgit.api.TransportCommand;
29  import org.eclipse.jgit.transport.URIish;
30  import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
31  
32  import com.cronutils.model.Cron;
33  
34  import com.linecorp.centraldogma.server.command.CommandExecutor;
35  import com.linecorp.centraldogma.server.internal.mirror.credential.AccessTokenMirrorCredential;
36  import com.linecorp.centraldogma.server.internal.mirror.credential.PasswordMirrorCredential;
37  import com.linecorp.centraldogma.server.mirror.MirrorCredential;
38  import com.linecorp.centraldogma.server.mirror.MirrorDirection;
39  import com.linecorp.centraldogma.server.storage.repository.Repository;
40  
41  final class DefaultGitMirror extends AbstractGitMirror {
42  
43      private static final Consumer<TransportCommand<?, ?>> NOOP_CONFIGURATOR = command -> {};
44  
45      DefaultGitMirror(Cron schedule, MirrorDirection direction, MirrorCredential credential,
46                       Repository localRepo, String localPath,
47                       URI remoteRepoUri, String remotePath, @Nullable String remoteBranch,
48                       @Nullable String gitignore) {
49          super(schedule, direction, credential, localRepo, localPath, remoteRepoUri, remotePath, remoteBranch,
50                gitignore);
51      }
52  
53      @Override
54      protected void mirrorLocalToRemote(File workDir, int maxNumFiles, long maxNumBytes) throws Exception {
55          try (GitWithAuth git = openGit(workDir, transportCommandConfigurator())) {
56              mirrorLocalToRemote(git, maxNumFiles, maxNumBytes);
57          }
58      }
59  
60      private Consumer<TransportCommand<?, ?>> transportCommandConfigurator() {
61          final MirrorCredential c = credential();
62          switch (remoteRepoUri().getScheme()) {
63              case SCHEME_GIT_HTTP:
64              case SCHEME_GIT_HTTPS:
65                  if (c instanceof PasswordMirrorCredential) {
66                      final PasswordMirrorCredential cred = (PasswordMirrorCredential) c;
67                      return command -> command.setCredentialsProvider(
68                              new UsernamePasswordCredentialsProvider(cred.username(), cred.password()));
69                  }
70                  if (c instanceof AccessTokenMirrorCredential) {
71                      final AccessTokenMirrorCredential cred = (AccessTokenMirrorCredential) c;
72                      return command -> command.setCredentialsProvider(
73                              new UsernamePasswordCredentialsProvider("token", cred.accessToken()));
74                  }
75                  break;
76          }
77          return NOOP_CONFIGURATOR;
78      }
79  
80      @Override
81      protected void mirrorRemoteToLocal(File workDir, CommandExecutor executor,
82                                         int maxNumFiles, long maxNumBytes) throws Exception {
83          try (GitWithAuth git = openGit(workDir, transportCommandConfigurator())) {
84              mirrorRemoteToLocal(git, executor, maxNumFiles, maxNumBytes);
85          }
86      }
87  
88      private GitWithAuth openGit(File workDir, Consumer<TransportCommand<?, ?>> configurator) throws Exception {
89          final String scheme = remoteRepoUri().getScheme();
90          final String jGitUri;
91          if (scheme.startsWith("git+")) {
92              // Convert the remoteRepoUri into the URI accepted by jGit by removing the 'git+' prefix.
93              jGitUri = remoteRepoUri().toASCIIString().substring(4);
94          } else {
95              jGitUri = remoteRepoUri().toASCIIString();
96          }
97          return openGit(workDir, new URIish(jGitUri), configurator);
98      }
99  }