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.time.Instant;
25  import java.util.function.Consumer;
26  
27  import javax.annotation.Nullable;
28  
29  import org.eclipse.jgit.api.TransportCommand;
30  import org.eclipse.jgit.transport.URIish;
31  import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
32  
33  import com.cronutils.model.Cron;
34  
35  import com.linecorp.centraldogma.server.command.CommandExecutor;
36  import com.linecorp.centraldogma.server.credential.Credential;
37  import com.linecorp.centraldogma.server.internal.credential.AccessTokenCredential;
38  import com.linecorp.centraldogma.server.internal.credential.PasswordCredential;
39  import com.linecorp.centraldogma.server.mirror.MirrorDirection;
40  import com.linecorp.centraldogma.server.mirror.MirrorResult;
41  import com.linecorp.centraldogma.server.storage.repository.Repository;
42  
43  final class DefaultGitMirror extends AbstractGitMirror {
44  
45      private static final Consumer<TransportCommand<?, ?>> NOOP_CONFIGURATOR = command -> {};
46  
47      DefaultGitMirror(String id, boolean enabled, @Nullable Cron schedule, MirrorDirection direction,
48                       Credential credential, Repository localRepo, String localPath,
49                       URI remoteRepoUri, String remotePath, String remoteBranch,
50                       @Nullable String gitignore, @Nullable String zone) {
51          super(id, enabled, schedule, direction, credential, localRepo, localPath, remoteRepoUri, remotePath,
52                remoteBranch, gitignore, zone);
53      }
54  
55      @Override
56      protected MirrorResult mirrorLocalToRemote(File workDir, int maxNumFiles, long maxNumBytes,
57                                                 Instant triggeredTime)
58              throws Exception {
59          try (GitWithAuth git = openGit(workDir, transportCommandConfigurator())) {
60              return mirrorLocalToRemote(git, maxNumFiles, maxNumBytes, triggeredTime);
61          }
62      }
63  
64      private Consumer<TransportCommand<?, ?>> transportCommandConfigurator() {
65          final Credential c = credential();
66          switch (remoteRepoUri().getScheme()) {
67              case SCHEME_GIT_HTTP:
68              case SCHEME_GIT_HTTPS:
69                  if (c instanceof PasswordCredential) {
70                      final PasswordCredential cred = (PasswordCredential) c;
71                      return command -> command.setCredentialsProvider(
72                              new UsernamePasswordCredentialsProvider(cred.username(), cred.password()));
73                  }
74                  if (c instanceof AccessTokenCredential) {
75                      final AccessTokenCredential cred = (AccessTokenCredential) c;
76                      return command -> command.setCredentialsProvider(
77                              new UsernamePasswordCredentialsProvider("token", cred.accessToken()));
78                  }
79                  break;
80          }
81          return NOOP_CONFIGURATOR;
82      }
83  
84      @Override
85      protected MirrorResult mirrorRemoteToLocal(File workDir, CommandExecutor executor,
86                                                 int maxNumFiles, long maxNumBytes, Instant triggeredTime)
87              throws Exception {
88          try (GitWithAuth git = openGit(workDir, transportCommandConfigurator())) {
89              return mirrorRemoteToLocal(git, executor, maxNumFiles, maxNumBytes, triggeredTime);
90          }
91      }
92  
93      private GitWithAuth openGit(File workDir, Consumer<TransportCommand<?, ?>> configurator) throws Exception {
94          final String scheme = remoteRepoUri().getScheme();
95          final String jGitUri;
96          if (scheme.startsWith("git+")) {
97              // Convert the remoteRepoUri into the URI accepted by jGit by removing the 'git+' prefix.
98              jGitUri = remoteRepoUri().toASCIIString().substring(4);
99          } else {
100             jGitUri = remoteRepoUri().toASCIIString();
101         }
102         return openGit(workDir, new URIish(jGitUri), configurator);
103     }
104 }