DiffCommand.java

  1. package org.docascode.api;

  2. import org.docascode.api.core.DocAsCodeRepository;
  3. import org.docascode.api.core.errors.DocAsCodeException;
  4. import org.docascode.api.diff.Differencer;
  5. import org.docascode.api.event.Event;
  6. import org.docascode.api.retrieve.GitRetriever;
  7. import org.eclipse.aether.resolution.ArtifactResult;
  8. import org.eclipse.aether.version.Version;
  9. import org.eclipse.jgit.lib.*;
  10. import org.eclipse.jgit.revwalk.RevCommit;
  11. import org.eclipse.jgit.revwalk.RevWalk;

  12. import java.io.IOException;
  13. import java.nio.file.Files;
  14. import java.nio.file.Paths;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17. import java.util.Map;
  18. import java.io.File;

  19. public class DiffCommand extends DocAsCodeCommand<DiffCommand>{
  20.     private String oldRevision;

  21.     public DiffCommand setOldRevision(String oldRevision){
  22.         this.oldRevision = oldRevision;
  23.         return this;
  24.     }

  25.     private String newRevision;

  26.     public DiffCommand setNewRevision(String newRevision){
  27.         this.newRevision = newRevision;
  28.         return this;
  29.     }

  30.     private String revision;

  31.     public DiffCommand setRevision(String revision){
  32.         this.revision = revision;
  33.         return this;
  34.     }

  35.     private File toFile;

  36.     public DiffCommand toFile(File toFile){
  37.         this.toFile = toFile;
  38.         return this;
  39.     }

  40.     private File file;

  41.     public DiffCommand setFile(File file){
  42.         this.file = file;
  43.         return this;
  44.     }

  45.     DiffCommand(DocAsCodeRepository repo) {
  46.         super(repo);
  47.     }

  48.     private boolean openAtEnd = false;

  49.     public DiffCommand openAtEnd(boolean openAtEnd){
  50.         this.openAtEnd = openAtEnd;
  51.         return this;
  52.     }

  53.     private File resolve(String revision) throws DocAsCodeException {
  54.         String path = getRepository().relativize(file);
  55.         Map<String, org.eclipse.aether.artifact.Artifact> artifactMap =
  56.                 ((DocAsCodeRepository) getRepository().addListener(this)).chrono().toArtifactFileMap();
  57.         if (artifactMap.keySet().contains(path)){
  58.             if (revision.equals("WorkTree")){
  59.                 return file;
  60.             }
  61.             org.eclipse.aether.artifact.Artifact artifact = artifactMap.get(path);
  62.             List<Version> listVersion = getRepository().mvn()
  63.                     .addRemoteRepositories(null) //default repository
  64.                     .getVersionRange(artifact);
  65.             List<String> listVersionString = new ArrayList<>();
  66.             for (Version v : listVersion){
  67.                 listVersionString.add(v.toString());
  68.             }
  69.             if (listVersionString.contains(revision) ||
  70.                     (!listVersionString.isEmpty() && revision.equals("LATEST")) ){
  71.                 artifact = artifact.setVersion(revision);
  72.                 ArtifactResult artifactResult = getRepository().mvn().resolve(artifact);
  73.                 return artifactResult.getArtifact().getFile();
  74.             }
  75.         }
  76.         try (RevWalk revWalk = new RevWalk(getRepository().git())){
  77.             ObjectId revisionId = getRepository().git().resolve(revision);
  78.             if (revisionId!= null){
  79.                 RevCommit commit = revWalk.parseCommit(revisionId);
  80.                 return new GitRetriever()
  81.                         .setCommit(commit)
  82.                         .setPath(path)
  83.                         .setRepository(getRepository().git())
  84.                         .toDir(new File(
  85.                                 getRepository().getTmpDir().getAbsolutePath(),
  86.                                 commit.getName()))
  87.                         .call();
  88.             } else {
  89.                 Event e = new Event(this);
  90.                 e.setMessage(String.format(
  91.                         "File '%s' not found at revision '%s'...",
  92.                         path,
  93.                         revision));
  94.                 fireEvent(e);
  95.                 return null;
  96.             }
  97.         } catch (IOException e) {
  98.             throw new DocAsCodeException(
  99.                 String.format(
  100.                     "Revision '%s' not found in git repository",
  101.                     revision),
  102.                 e
  103.             );
  104.         }
  105.     }

  106.     @Override
  107.     public DiffCommand call() throws DocAsCodeException {
  108.         File newFile;
  109.         if (newRevision == null){
  110.             newFile = file;
  111.             newRevision = "WorkTree";
  112.         } else {
  113.             newFile = resolve(newRevision);
  114.         }
  115.         if (revision==null){
  116.             revision = oldRevision+":"+newRevision;
  117.         }
  118.         File oldFile = resolve(oldRevision);
  119.         try {
  120.             Files.deleteIfExists(Paths.get(toFile.getAbsolutePath()));
  121.             toFile.getParentFile().mkdirs();
  122.             if (!toFile.createNewFile()){
  123.                 throw new DocAsCodeException(
  124.                         String.format(
  125.                                 "Unable to create file '%s'",
  126.                                 toFile));
  127.             }
  128.         } catch (IOException e) {
  129.             throw new DocAsCodeException(
  130.                     String.format(
  131.                             "Unable to create file '%s'",
  132.                             toFile),e);
  133.         }
  134.         Differencer diff = (Differencer) new Differencer().addListener(this);
  135.         diff.setBaseFile(oldFile)
  136.                 .setRevisedFile(newFile)
  137.                 .setRevision(this.revision)
  138.                 .setTargetFile(toFile)
  139.                 .openAtEnd(openAtEnd)
  140.                 .diff();
  141.         return this;
  142.     }
  143. }