1 package org.cyclopsgroup.gitcon.jgit;
2
3 import java.io.File;
4 import java.io.IOException;
5
6 import org.apache.commons.io.FileUtils;
7 import org.apache.commons.lang.StringUtils;
8 import org.apache.commons.lang.SystemUtils;
9 import org.apache.commons.lang.Validate;
10 import org.apache.commons.logging.Log;
11 import org.apache.commons.logging.LogFactory;
12 import org.cyclopsgroup.gitcon.Source;
13 import org.eclipse.jgit.api.CloneCommand;
14 import org.eclipse.jgit.api.Git;
15 import org.eclipse.jgit.api.PullResult;
16 import org.eclipse.jgit.api.errors.GitAPIException;
17 import org.eclipse.jgit.lib.Ref;
18 import org.eclipse.jgit.transport.CredentialsProvider;
19 import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44 public class JGitSource
45 implements Source
46 {
47 private static final Log LOG = LogFactory.getLog( JGitSource.class );
48
49 private volatile String branchOrCommit;
50
51 private String sshIdentity;
52
53 private Boolean buildInSshIdentityUsed;
54
55 private CredentialsProvider credentialsProvider;
56
57 private JGitCallExecutor executor;
58
59 private Git git;
60
61 private final String repoUri;
62
63
64
65
66
67
68
69 public JGitSource( String repoUri )
70 {
71 Validate.notNull( repoUri, "Git repository URI can not be NULL" );
72 this.repoUri = repoUri;
73 }
74
75 public String getBranchOrCommmit()
76 {
77 return branchOrCommit;
78 }
79
80
81
82
83 @Override
84 public File initWorkingDirectory( File workingDirectory )
85 throws GitAPIException, IOException
86 {
87
88 File sourceDirectory =
89 new File( workingDirectory.getAbsolutePath()
90 + SystemUtils.FILE_SEPARATOR + "gitrepo" );
91 if ( sourceDirectory.mkdirs() )
92 {
93 LOG.info( "Created GIT repo directory " + sourceDirectory );
94 }
95
96
97 File sshKey = null;
98 if ( buildInSshIdentityUsed == Boolean.TRUE
99 || StringUtils.equalsIgnoreCase( sshIdentity, "buildin" ) )
100 {
101 sshKey =
102 new File( workingDirectory.getAbsolutePath()
103 + SystemUtils.FILE_SEPARATOR + "gitconreader-ssh.key" );
104 FileUtils.copyURLToFile( getClass().getClassLoader().getResource( "META-INF/gitcon/gitconreader-ssh.key" ),
105 sshKey );
106 LOG.info( "Build-in SSH private key is copied into " + sshKey );
107
108 }
109 else if ( sshIdentity != null
110 && !sshIdentity.equalsIgnoreCase( "default" ) )
111 {
112 sshKey = new File( sshIdentity );
113 LOG.info( "About to use specified SSH key " + sshIdentity );
114 }
115 else
116 {
117 LOG.info( "Default system SSH key will apply" );
118 }
119
120 if ( sshKey == null )
121 {
122 executor = JGitCallExecutor.synchronize( JGitCallExecutor.direct() );
123 }
124 else if ( !sshKey.canRead() )
125 {
126 throw new IllegalStateException( "Configured SSH private key "
127 + sshKey + " is not accessible" );
128 }
129 else
130 {
131 executor =
132 JGitCallExecutor.withSshPrivateKey( sshKey.getAbsolutePath() );
133 LOG.info( "JGit executor is set with build-in SSH key " + sshKey );
134 }
135
136
137 final CloneCommand clone =
138 Git.cloneRepository().setDirectory( sourceDirectory ).setURI( repoUri );
139 if ( credentialsProvider != null )
140 {
141 clone.setCredentialsProvider( credentialsProvider );
142
143 }
144 LOG.info( "Running git clone " + repoUri + " against "
145 + sourceDirectory );
146
147 git = executor.invokeCall( new JGitCall<Git>()
148 {
149 @Override
150 public Git call()
151 throws GitAPIException
152 {
153 return clone.call();
154 }
155 } );
156
157
158 if ( branchOrCommit != null )
159 {
160 LOG.info( "Calling git checkout " + branchOrCommit + " ..." );
161 Ref result = executor.invokeCall( new JGitCall<Ref>()
162 {
163 public Ref call()
164 throws GitAPIException
165 {
166 return git.checkout().setName( branchOrCommit ).call();
167 }
168 } );
169 LOG.info( "Git checkout returned " + result );
170 }
171 return sourceDirectory;
172 }
173
174
175
176
177
178
179
180
181
182 public void setBranchOrCommit( String branch )
183 {
184 this.branchOrCommit = branch;
185 }
186
187
188
189
190
191
192
193
194 public void setBuildInSshIdentityUsed( boolean buildInSshIdentityUsed )
195 {
196 this.buildInSshIdentityUsed = buildInSshIdentityUsed;
197 }
198
199
200
201
202
203
204
205
206
207
208
209 public void setSshIdentity( String privateKeyPath )
210 {
211 this.sshIdentity = privateKeyPath;
212 }
213
214
215
216
217
218
219
220 public void setSshIdentityFile( File privateKeyFile )
221 {
222 setSshIdentity( privateKeyFile == null ? null
223 : privateKeyFile.getAbsolutePath() );
224 }
225
226
227
228
229
230
231
232 public void setUserPassword( String userAndPassword )
233 {
234 int position = userAndPassword.indexOf( ':' );
235 Validate.isTrue( position > 0
236 && position < userAndPassword.length() - 1,
237 "Input must be <username>:<password>, but it is "
238 + userAndPassword );
239 setUserPassword( userAndPassword.substring( 0, position ),
240 userAndPassword.substring( position + 1 ) );
241 }
242
243
244
245
246
247
248
249
250
251 public void setUserPassword( String user, String password )
252 {
253 Validate.notNull( user, "User name must be supplied" );
254 Validate.notNull( password, "Password must be supplied" );
255
256 if ( credentialsProvider != null )
257 {
258 throw new IllegalStateException(
259 "Credentials provider can only be set for once. It's already "
260 + credentialsProvider );
261 }
262
263 this.credentialsProvider =
264 new UsernamePasswordCredentialsProvider( user, password );
265 LOG.info( "Credentials provider is set to user/password instance" );
266 }
267
268
269
270
271
272
273
274 @Override
275 public void updateWorkingDirectory( File workingDirectory )
276 throws GitAPIException
277 {
278 LOG.info( "Running a git pull command ... " );
279 PullResult result = executor.invokeCall( new JGitCall<PullResult>()
280 {
281 public PullResult call()
282 throws GitAPIException
283 {
284 return git.pull().call();
285 }
286 } );
287 LOG.info( "Pull command returned " + result );
288 }
289 }