1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kathrynhuxtable.maven.wagon.gitsite;
17
18 import java.io.File;
19 import java.io.IOException;
20
21 import java.text.DecimalFormat;
22
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Random;
26 import java.util.Stack;
27
28 import org.apache.maven.scm.CommandParameter;
29 import org.apache.maven.scm.CommandParameters;
30 import org.apache.maven.scm.ScmBranch;
31 import org.apache.maven.scm.ScmException;
32 import org.apache.maven.scm.ScmFile;
33 import org.apache.maven.scm.ScmFileSet;
34 import org.apache.maven.scm.ScmResult;
35 import org.apache.maven.scm.ScmVersion;
36 import org.apache.maven.scm.command.add.AddScmResult;
37 import org.apache.maven.scm.command.checkin.CheckInScmResult;
38 import org.apache.maven.scm.command.checkout.CheckOutScmResult;
39 import org.apache.maven.scm.command.list.ListScmResult;
40 import org.apache.maven.scm.log.ScmLogger;
41 import org.apache.maven.scm.manager.NoSuchScmProviderException;
42 import org.apache.maven.scm.manager.ScmManager;
43 import org.apache.maven.scm.provider.ScmProvider;
44 import org.apache.maven.scm.provider.ScmProviderRepository;
45 import org.apache.maven.scm.provider.ScmProviderRepositoryWithHost;
46 import org.apache.maven.scm.provider.git.command.GitCommand;
47 import org.apache.maven.scm.provider.git.gitexe.GitExeScmProvider;
48 import org.apache.maven.scm.repository.ScmRepository;
49 import org.apache.maven.scm.repository.ScmRepositoryException;
50 import org.apache.maven.wagon.AbstractWagon;
51 import org.apache.maven.wagon.ConnectionException;
52 import org.apache.maven.wagon.ResourceDoesNotExistException;
53 import org.apache.maven.wagon.TransferFailedException;
54 import org.apache.maven.wagon.authentication.AuthenticationException;
55 import org.apache.maven.wagon.authentication.AuthenticationInfo;
56 import org.apache.maven.wagon.authorization.AuthorizationException;
57 import org.apache.maven.wagon.events.TransferEvent;
58 import org.apache.maven.wagon.proxy.ProxyInfoProvider;
59 import org.apache.maven.wagon.repository.Repository;
60 import org.apache.maven.wagon.resource.Resource;
61
62 import org.codehaus.plexus.util.FileUtils;
63 import org.codehaus.plexus.util.StringUtils;
64
65 import org.kathrynhuxtable.maven.wagon.gitsite.git.GitSiteCheckInCommand;
66 import org.kathrynhuxtable.maven.wagon.gitsite.git.GitSiteCheckOutCommand;
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107 public class GitSiteWagon extends AbstractWagon {
108
109
110
111
112
113
114 private ScmManager scmManager;
115
116
117 private String siteBranch;
118
119
120 private File checkoutDirectory;
121
122
123
124
125
126
127 public ScmManager getScmManager() {
128 return scmManager;
129 }
130
131
132
133
134
135
136 public void setScmManager(ScmManager scmManager) {
137 this.scmManager = scmManager;
138 }
139
140
141
142
143
144
145 public String getSiteBranch() {
146 return siteBranch;
147 }
148
149
150
151
152
153
154 public void setSiteBranch(String siteBranch) {
155 this.siteBranch = siteBranch;
156 }
157
158
159
160
161
162
163
164 public File getCheckoutDirectory() {
165 return checkoutDirectory;
166 }
167
168
169
170
171
172
173
174 public void setCheckoutDirectory(File checkoutDirectory) {
175 this.checkoutDirectory = checkoutDirectory;
176 }
177
178
179
180
181
182
183
184
185
186
187
188
189 public ScmProvider getScmProvider(String scmType) throws NoSuchScmProviderException {
190 return getScmManager().getProviderByType(scmType);
191 }
192
193
194
195
196
197
198 public void openConnectionInternal() throws ConnectionException {
199 if (checkoutDirectory == null) {
200 checkoutDirectory = createCheckoutDirectory();
201 }
202
203 if (checkoutDirectory.exists()) {
204 removeCheckoutDirectory();
205 }
206
207 checkoutDirectory.mkdirs();
208 }
209
210
211
212
213
214
215 private File createCheckoutDirectory() {
216 File checkoutDirectory;
217
218 DecimalFormat fmt = new DecimalFormat("#####");
219
220 Random rand = new Random(System.currentTimeMillis() + Runtime.getRuntime().freeMemory());
221
222 do {
223 checkoutDirectory = new File(System.getProperty("java.io.tmpdir"),
224 "wagon-scm" + fmt.format(Math.abs(rand.nextInt())) + ".checkout");
225 } while (checkoutDirectory.exists());
226
227 return checkoutDirectory;
228 }
229
230
231
232
233
234
235 private void removeCheckoutDirectory() throws ConnectionException {
236 if (checkoutDirectory == null) {
237 return;
238 }
239
240 try {
241 FileUtils.deleteDirectory(checkoutDirectory);
242 } catch (IOException e) {
243 throw new ConnectionException("Unable to cleanup checkout directory", e);
244 }
245 }
246
247
248
249
250
251
252
253
254
255
256
257
258 private ScmRepository getScmRepository(String url) throws ScmRepositoryException, NoSuchScmProviderException {
259 String username = null;
260
261 String password = null;
262
263 String privateKey = null;
264
265 String passphrase = null;
266
267 if (authenticationInfo != null) {
268 username = authenticationInfo.getUserName();
269
270 password = authenticationInfo.getPassword();
271
272 privateKey = authenticationInfo.getPrivateKey();
273
274 passphrase = authenticationInfo.getPassphrase();
275 }
276
277 ScmRepository scmRepository = getScmManager().makeScmRepository(url);
278
279 ScmProviderRepository providerRepository = scmRepository.getProviderRepository();
280
281 if (StringUtils.isNotEmpty(username)) {
282 providerRepository.setUser(username);
283 }
284
285 if (StringUtils.isNotEmpty(password)) {
286 providerRepository.setPassword(password);
287 }
288
289 if (providerRepository instanceof ScmProviderRepositoryWithHost) {
290 ScmProviderRepositoryWithHost providerRepo = (ScmProviderRepositoryWithHost) providerRepository;
291
292 if (StringUtils.isNotEmpty(privateKey)) {
293 providerRepo.setPrivateKey(privateKey);
294 }
295
296 if (StringUtils.isNotEmpty(passphrase)) {
297 providerRepo.setPassphrase(passphrase);
298 }
299 }
300
301 return scmRepository;
302 }
303
304
305
306
307
308
309
310
311
312
313 private void checkIn(ScmProvider scmProvider, ScmRepository scmRepository, String msg) throws ScmException {
314 CommandParameters parameters = new CommandParameters();
315
316 parameters.setScmVersion(CommandParameter.SCM_VERSION, new ScmBranch(siteBranch));
317
318 parameters.setString(CommandParameter.MESSAGE, msg);
319
320 ScmResult result = (CheckInScmResult) executeCommand((GitExeScmProvider) scmProvider, new GitSiteCheckInCommand(),
321 scmRepository.getProviderRepository(),
322 new ScmFileSet(checkoutDirectory), parameters);
323
324 checkScmResult(result);
325 }
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342 private String checkOut(ScmProvider scmProvider, ScmRepository scmRepository, String targetName, Resource resource)
343 throws TransferFailedException {
344 checkoutDirectory = createCheckoutDirectory();
345
346 Stack<String> stack = new Stack<String>();
347
348 String target = targetName;
349
350
351
352
353
354
355 try {
356 while (target.length() > 0
357 && !scmProvider.list(scmRepository, new ScmFileSet(new File("."), new File(target)), false, (ScmVersion) null)
358 .isSuccess()) {
359 stack.push(getFilename(target));
360 target = getDirname(target);
361 }
362 } catch (ScmException e) {
363 fireTransferError(resource, e, TransferEvent.REQUEST_PUT);
364
365 throw new TransferFailedException("Error listing repository: " + e.getMessage(), e);
366 }
367
368
369
370
371
372
373
374 String url = getRepository().getUrl() + targetName;
375 String relPath = "";
376
377 if (!url.endsWith(".git")) {
378 final int iGitSuffix = url.lastIndexOf(".git");
379 if (iGitSuffix > 0) {
380 relPath = url.substring(iGitSuffix + 5) + '/';
381 url = url.substring(0, iGitSuffix + 4);
382 }
383 }
384 final ScmLogger logger = ((GitExeScmProvider)scmProvider).getLogger();
385 logger.debug("checkOut url: " + url);
386 logger.debug("checkOut relPath: " + relPath);
387
388
389
390
391
392
393 try {
394 scmRepository = getScmRepository(url);
395
396 CommandParameters parameters = new CommandParameters();
397
398 parameters.setScmVersion(CommandParameter.SCM_VERSION, new ScmBranch(siteBranch));
399
400 parameters.setString(CommandParameter.RECURSIVE, "false");
401
402 CheckOutScmResult ret = (CheckOutScmResult) executeCommand((GitExeScmProvider) scmProvider, new GitSiteCheckOutCommand(),
403 scmRepository.getProviderRepository(),
404 new ScmFileSet(new File(checkoutDirectory, "")), parameters);
405
406 checkScmResult(ret);
407 } catch (ScmException e) {
408 fireTransferError(resource, e, TransferEvent.REQUEST_PUT);
409
410 throw new TransferFailedException("Error checking out: " + e.getMessage(), e);
411 }
412
413
414
415 while (!stack.isEmpty()) {
416 String p = (String) stack.pop();
417
418 relPath += p + '/';
419 logger.debug(" * checkOut relPath: " + relPath);
420
421 File newDir = new File(checkoutDirectory, relPath);
422
423 if (!newDir.mkdirs()) {
424 throw new TransferFailedException("Failed to create directory " + newDir.getAbsolutePath() + "; parent should exist: "
425 + checkoutDirectory);
426 }
427
428 try {
429 addFiles(scmProvider, scmRepository, checkoutDirectory, relPath);
430 } catch (ScmException e) {
431 fireTransferError(resource, e, TransferEvent.REQUEST_PUT);
432
433 throw new TransferFailedException("Failed to add directory " + newDir + " to working copy", e);
434 }
435 }
436
437 return relPath;
438 }
439
440 private List<File> buildFiles(ScmProvider scmProvider, File basedir, String scmFilePath) {
441 List<File> result = new ArrayList<File>();
442 if (scmFilePath.length() != 0) {
443 result.add(new File(scmFilePath));
444 }
445 String reservedScmFile = scmProvider.getScmSpecificFilename();
446 File scmFile = new File(basedir, scmFilePath);
447 if (scmFile.isDirectory()) {
448 File[] f = scmFile.listFiles();
449
450 for (int i = 0; i < f.length; i++) {
451 if (reservedScmFile != null && !reservedScmFile.equals(f[i].getName())) {
452 result.addAll(buildFiles(scmProvider, basedir, (scmFilePath.length() == 0 ? "" : scmFilePath + "/") + f[i].getName()));
453 }
454 }
455 }
456 return result;
457 }
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473 private int addFiles(ScmProvider scmProvider, ScmRepository scmRepository, File basedir, String scmFilePath) throws ScmException {
474 AddScmResult result = scmProvider.add(scmRepository, new ScmFileSet(basedir, buildFiles(scmProvider, basedir, scmFilePath)));
475
476
477
478
479
480 if (!result.isSuccess()) {
481 result = scmProvider.add(scmRepository, new ScmFileSet(basedir, new File(scmFilePath)));
482 }
483
484 return result.getAddedFiles().size();
485 }
486
487
488
489
490
491
492
493
494 public boolean supportsDirectoryCopy() {
495 return true;
496 }
497
498
499
500
501
502
503 public void connect(Repository repository, AuthenticationInfo authenticationInfo, ProxyInfoProvider proxyInfoProvider)
504 throws ConnectionException, AuthenticationException {
505 String url = repository.getUrl();
506
507 if (url.startsWith("gitsite:")) {
508 url = url.substring(8);
509 int index = url.indexOf(':');
510
511 if (index > -1) {
512 siteBranch = url.substring(index + 1);
513 url = url.substring(0, index);
514 } else if (url.indexOf(".github.com.git") != -1) {
515
516 siteBranch = "master";
517 }else {
518 siteBranch = "gh-pages";
519 }
520
521 if (url.startsWith("file:///"))
522 url = "scm:git:" + url;
523 else
524 url = "scm:git:ssh://" + url;
525 repository.setUrl(url);
526 }
527
528 super.connect(repository, authenticationInfo, proxyInfoProvider);
529 }
530
531
532
533
534 public void put(File source, String destination) throws TransferFailedException {
535 putResource(source, destination);
536 }
537
538
539
540
541 public void putDirectory(File sourceDirectory, String destinationDirectory) throws TransferFailedException,
542 ResourceDoesNotExistException, AuthorizationException {
543 if (!sourceDirectory.isDirectory()) {
544 throw new IllegalArgumentException("Source is not a directory: " + sourceDirectory);
545 }
546
547 putResource(sourceDirectory, destinationDirectory);
548 }
549
550 private void putResource(File sourceDirectory, String destinationDirectory) throws TransferFailedException {
551 Resource target = new Resource(destinationDirectory);
552
553 firePutInitiated(target, sourceDirectory);
554
555 try {
556 ScmRepository scmRepository = getScmRepository(getRepository().getUrl());
557
558 target.setContentLength(sourceDirectory.length());
559 target.setLastModified(sourceDirectory.lastModified());
560
561 firePutStarted(target, sourceDirectory);
562
563 String msg = "Wagon: Deploying " + sourceDirectory.getName() + " to repository";
564
565 ScmProvider scmProvider = getScmProvider(scmRepository.getProvider());
566
567 String checkoutTargetName = sourceDirectory.isDirectory() ? destinationDirectory : getDirname(destinationDirectory);
568 String relPath = checkOut(scmProvider, scmRepository, checkoutTargetName, target);
569
570 File newCheckoutDirectory = new File(checkoutDirectory, relPath);
571
572 File scmFile = new File(newCheckoutDirectory, sourceDirectory.isDirectory() ? "" : getFilename(destinationDirectory));
573
574 boolean fileAlreadyInScm = scmFile.exists();
575
576 if (!scmFile.equals(sourceDirectory)) {
577 if (sourceDirectory.isDirectory()) {
578 FileUtils.copyDirectoryStructure(sourceDirectory, scmFile);
579 } else {
580 FileUtils.copyFile(sourceDirectory, scmFile);
581 }
582 }
583
584 if (!fileAlreadyInScm || scmFile.isDirectory()) {
585 int addedFiles = addFiles(scmProvider, scmRepository, newCheckoutDirectory,
586 sourceDirectory.isDirectory() ? "" : scmFile.getName());
587
588 if (!fileAlreadyInScm && addedFiles == 0) {
589 throw new ScmException("Unable to add file to SCM: " + scmFile + "; see error messages above for more information");
590 }
591 }
592
593 checkIn(scmProvider, scmRepository, msg);
594 } catch (ScmException e) {
595 e.printStackTrace();
596 fireTransferError(target, e, TransferEvent.REQUEST_GET);
597
598 System.exit(1);
599 throw new TransferFailedException("Error interacting with SCM: " + e.getMessage(), e);
600 } catch (IOException e) {
601 fireTransferError(target, e, TransferEvent.REQUEST_GET);
602
603 throw new TransferFailedException("Error interacting with SCM: " + e.getMessage(), e);
604 }
605
606 if (sourceDirectory.isFile()) {
607 postProcessListeners(target, sourceDirectory, TransferEvent.REQUEST_PUT);
608 }
609
610 firePutCompleted(target, sourceDirectory);
611 }
612
613
614
615
616
617
618
619
620 private void checkScmResult(ScmResult result) throws ScmException {
621 if (!result.isSuccess()) {
622 throw new ScmException("Unable to commit file. " + result.getProviderMessage() + " "
623 + (result.getCommandOutput() == null ? "" : result.getCommandOutput()));
624 }
625 }
626
627
628
629
630 public void closeConnection() throws ConnectionException {
631 removeCheckoutDirectory();
632 }
633
634
635
636
637
638 public boolean getIfNewer(String resourceName, File destination, long timestamp) throws TransferFailedException,
639 ResourceDoesNotExistException, AuthorizationException {
640 throw new UnsupportedOperationException("Not currently supported: getIfNewer");
641 }
642
643
644
645
646 public void get(String resourceName, File destination) throws TransferFailedException, ResourceDoesNotExistException,
647 AuthorizationException {
648 throw new UnsupportedOperationException("Not currently supported: get");
649 }
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665 public List<String> getFileList(String resourcePath) throws TransferFailedException, ResourceDoesNotExistException,
666 AuthorizationException {
667 try {
668 ScmRepository repository = getScmRepository(getRepository().getUrl());
669 ScmProvider provider = getScmProvider(repository.getProvider());
670 ListScmResult result = provider.list(repository,
671 new ScmFileSet(new File("."), new File(resourcePath)), false, (ScmVersion) null);
672
673 if (!result.isSuccess()) {
674 throw new ResourceDoesNotExistException(result.getProviderMessage());
675 }
676
677 List<String> files = new ArrayList<String>();
678
679 for (ScmFile f : getListScmResultFiles(result)) {
680 files.add(f.getPath());
681 System.out.println("LIST FILE: " + f + " (path=" + f.getPath() + ")");
682 }
683
684 return files;
685 } catch (ScmException e) {
686 throw new TransferFailedException("Error getting filelist from SCM", e);
687 }
688 }
689
690
691
692
693
694
695
696
697
698 @SuppressWarnings("unchecked")
699 private List<ScmFile> getListScmResultFiles(ListScmResult result) {
700 return (List<ScmFile>) result.getFiles();
701 }
702
703
704
705
706 public boolean resourceExists(String resourceName) throws TransferFailedException, AuthorizationException {
707 try {
708 getFileList(resourceName);
709 return true;
710 } catch (ResourceDoesNotExistException e) {
711 return false;
712 }
713 }
714
715
716
717
718
719
720
721
722 private String getFilename(String filename) {
723 String fname = StringUtils.replace(filename, "/", File.separator);
724
725 return FileUtils.filename(fname);
726 }
727
728
729
730
731
732
733
734
735 private String getDirname(String filename) {
736 String fname = StringUtils.replace(filename, "/", File.separator);
737
738 return FileUtils.dirname(fname);
739 }
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754 protected ScmResult executeCommand(GitExeScmProvider scmProvider, GitCommand command, ScmProviderRepository repository,
755 ScmFileSet fileSet, CommandParameters parameters) throws ScmException {
756 command.setLogger(scmProvider.getLogger());
757
758 return command.execute(repository, fileSet, parameters);
759 }
760 }