mirror of
				https://github.com/scm-manager/scm-manager.git
				synced 2025-10-31 18:46:07 +01:00 
			
		
		
		
	revisit gpg api and use it with from git plugin
This commit is contained in:
		| @@ -33,16 +33,20 @@ import org.eclipse.jgit.lib.PersonIdent; | ||||
| import org.eclipse.jgit.revwalk.RevCommit; | ||||
| import org.eclipse.jgit.revwalk.RevWalk; | ||||
| import org.eclipse.jgit.treewalk.TreeWalk; | ||||
| import org.slf4j.Logger; | ||||
| import org.slf4j.LoggerFactory; | ||||
| import org.eclipse.jgit.util.RawParseUtils; | ||||
| import sonia.scm.security.GPG; | ||||
| import sonia.scm.security.PublicKey; | ||||
| import sonia.scm.util.Util; | ||||
|  | ||||
| import java.io.ByteArrayOutputStream; | ||||
| import java.io.Closeable; | ||||
| import java.io.IOException; | ||||
| import java.util.ArrayList; | ||||
| import java.util.Arrays; | ||||
| import java.util.Collection; | ||||
| import java.util.Collections; | ||||
| import java.util.List; | ||||
| import java.util.Optional; | ||||
|  | ||||
| //~--- JDK imports ------------------------------------------------------------ | ||||
|  | ||||
| @@ -50,121 +54,35 @@ import java.util.List; | ||||
|  * | ||||
|  * @author Sebastian Sdorra | ||||
|  */ | ||||
| public class GitChangesetConverter implements Closeable | ||||
| { | ||||
| public class GitChangesetConverter implements Closeable { | ||||
|  | ||||
|   /** | ||||
|    * the logger for GitChangesetConverter | ||||
|    */ | ||||
|   private static final Logger logger = | ||||
|     LoggerFactory.getLogger(GitChangesetConverter.class); | ||||
|  | ||||
|   //~--- constructors --------------------------------------------------------- | ||||
|  | ||||
|   /** | ||||
|    * Constructs ... | ||||
|    * | ||||
|    * | ||||
|    * @param repository | ||||
|    */ | ||||
|   GitChangesetConverter(org.eclipse.jgit.lib.Repository repository) | ||||
|   { | ||||
|     this(repository, null); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Constructs ... | ||||
|    * | ||||
|    * | ||||
|    * @param repository | ||||
|    * @param revWalk | ||||
|    */ | ||||
|   GitChangesetConverter(org.eclipse.jgit.lib.Repository repository, | ||||
|     RevWalk revWalk) | ||||
|   { | ||||
|     this.repository = repository; | ||||
|  | ||||
|     if (revWalk != null) | ||||
|     { | ||||
|       this.revWalk = revWalk; | ||||
|  | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|       this.revWalk = new RevWalk(repository); | ||||
|     } | ||||
|   private final GPG gpg; | ||||
|   private final Multimap<ObjectId, String> tags; | ||||
|   private final TreeWalk treeWalk; | ||||
|  | ||||
|   GitChangesetConverter(GPG gpg, org.eclipse.jgit.lib.Repository repository, RevWalk revWalk) { | ||||
|     this.gpg = gpg; | ||||
|     this.tags = GitUtil.createTagMap(repository, revWalk); | ||||
|     treeWalk = new TreeWalk(repository); | ||||
|     this.treeWalk = new TreeWalk(repository); | ||||
|   } | ||||
|  | ||||
|   //~--- methods -------------------------------------------------------------- | ||||
|  | ||||
|   /** | ||||
|    * Method description | ||||
|    * | ||||
|    */ | ||||
|   @Override | ||||
|   public void close() | ||||
|   { | ||||
|     GitUtil.release(treeWalk); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Method description | ||||
|    * | ||||
|    * | ||||
|    * @param commit | ||||
|    * | ||||
|    * @return | ||||
|    * | ||||
|    * @throws IOException | ||||
|    */ | ||||
|   public Changeset createChangeset(RevCommit commit) | ||||
|   { | ||||
|   public Changeset createChangeset(RevCommit commit) { | ||||
|     return createChangeset(commit, Collections.emptyList()); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Method description | ||||
|    * | ||||
|    * | ||||
|    * @param commit | ||||
|    * @param branch | ||||
|    * | ||||
|    * @return | ||||
|    * | ||||
|    * @throws IOException | ||||
|    */ | ||||
|   public Changeset createChangeset(RevCommit commit, String branch) | ||||
|   { | ||||
|   public Changeset createChangeset(RevCommit commit, String branch) { | ||||
|     return createChangeset(commit, Lists.newArrayList(branch)); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|    * Method description | ||||
|    * | ||||
|    * | ||||
|    * | ||||
|    * @param commit | ||||
|    * @param branches | ||||
|    * | ||||
|    * @return | ||||
|    * | ||||
|    * @throws IOException | ||||
|    */ | ||||
|   public Changeset createChangeset(RevCommit commit, List<String> branches) | ||||
|   { | ||||
|   public Changeset createChangeset(RevCommit commit, List<String> branches) { | ||||
|     String id = commit.getId().name(); | ||||
|     List<String> parentList = null; | ||||
|     RevCommit[] parents = commit.getParents(); | ||||
|  | ||||
|     if (Util.isNotEmpty(parents)) | ||||
|     { | ||||
|       parentList = new ArrayList<String>(); | ||||
|     if (Util.isNotEmpty(parents)) { | ||||
|       parentList = new ArrayList<>(); | ||||
|  | ||||
|       for (RevCommit parent : parents) | ||||
|       { | ||||
|       for (RevCommit parent : parents) { | ||||
|         parentList.add(parent.getId().name()); | ||||
|       } | ||||
|     } | ||||
| @@ -175,8 +93,7 @@ public class GitChangesetConverter implements Closeable | ||||
|     Person author = createPersonFor(authorIndent); | ||||
|     String message = commit.getFullMessage(); | ||||
|  | ||||
|     if (message != null) | ||||
|     { | ||||
|     if (message != null) { | ||||
|       message = message.trim(); | ||||
|     } | ||||
|  | ||||
| @@ -185,41 +102,73 @@ public class GitChangesetConverter implements Closeable | ||||
|       changeset.addContributor(new Contributor("Committed-by", createPersonFor(committerIdent))); | ||||
|     } | ||||
|  | ||||
|     if (parentList != null) | ||||
|     { | ||||
|     if (parentList != null) { | ||||
|       changeset.setParents(parentList); | ||||
|     } | ||||
|  | ||||
|     Collection<String> tagCollection = tags.get(commit.getId()); | ||||
|  | ||||
|     if (Util.isNotEmpty(tagCollection)) | ||||
|     { | ||||
|  | ||||
|     if (Util.isNotEmpty(tagCollection)) { | ||||
|       // create a copy of the tag collection to reduce memory on caching | ||||
|       changeset.getTags().addAll(Lists.newArrayList(tagCollection)); | ||||
|     } | ||||
|  | ||||
|     changeset.setBranches(branches); | ||||
|  | ||||
|     Signature signature = createSignature(commit); | ||||
|     if (signature != null) { | ||||
|       changeset.addSignature(signature); | ||||
|     } | ||||
|  | ||||
|     return changeset; | ||||
|   } | ||||
|  | ||||
|   private static final byte[] GPG_HEADER = {'g', 'p', 'g', 's', 'i', 'g'}; | ||||
|  | ||||
|   private Signature createSignature(RevCommit commit) { | ||||
|     byte[] raw = commit.getRawBuffer(); | ||||
|  | ||||
|     int start = RawParseUtils.headerStart(GPG_HEADER, raw, 0); | ||||
|     if (start < 0) { | ||||
|       return null; | ||||
|     } | ||||
|  | ||||
|     int end = RawParseUtils.headerEnd(raw, start); | ||||
|     byte[] signature = Arrays.copyOfRange(raw, start, end); | ||||
|  | ||||
|     String publicKeyId = gpg.findPublicKeyId(signature); | ||||
|  | ||||
|     Optional<PublicKey> publicKeyById = gpg.findPublicKey(publicKeyId); | ||||
|     if (!publicKeyById.isPresent()) { | ||||
|       // key not found | ||||
|       return new Signature(publicKeyId, "gpg", false, null); | ||||
|     } | ||||
|  | ||||
|     PublicKey publicKey = publicKeyById.get(); | ||||
|  | ||||
|     ByteArrayOutputStream baos = new ByteArrayOutputStream(); | ||||
|     try { | ||||
|       byte[] headerPrefix = Arrays.copyOfRange(raw, 0, start - GPG_HEADER.length - 1); | ||||
|       baos.write(headerPrefix); | ||||
|  | ||||
|       byte[] headerSuffix = Arrays.copyOfRange(raw, end + 1, raw.length); | ||||
|       baos.write(headerSuffix); | ||||
|     } catch (IOException ex) { | ||||
|       // this will never happen, because we are writing into memory | ||||
|       throw new IllegalStateException("failed to write into memory", ex); | ||||
|     } | ||||
|  | ||||
|     boolean verified = publicKey.verify(baos.toByteArray(), signature); | ||||
|     return new Signature(publicKeyId, "gpg", verified, publicKey.getOwner().orElse(null)); | ||||
|   } | ||||
|  | ||||
|   public Person createPersonFor(PersonIdent personIndent) { | ||||
|     return new Person(personIndent.getName(), personIndent.getEmailAddress()); | ||||
|   } | ||||
|  | ||||
|   @Override | ||||
|   public void close() { | ||||
|     GitUtil.release(treeWalk); | ||||
|   } | ||||
|  | ||||
|   //~--- fields --------------------------------------------------------------- | ||||
|  | ||||
|   /** Field description */ | ||||
|   private org.eclipse.jgit.lib.Repository repository; | ||||
|  | ||||
|   /** Field description */ | ||||
|   private RevWalk revWalk; | ||||
|  | ||||
|   /** Field description */ | ||||
|   private Multimap<ObjectId, String> tags; | ||||
|  | ||||
|   /** Field description */ | ||||
|   private TreeWalk treeWalk; | ||||
| } | ||||
|   | ||||
| @@ -26,15 +26,25 @@ package sonia.scm.repository; | ||||
|  | ||||
| import org.eclipse.jgit.lib.Repository; | ||||
| import org.eclipse.jgit.revwalk.RevWalk; | ||||
| import sonia.scm.security.GPG; | ||||
|  | ||||
| import javax.inject.Inject; | ||||
|  | ||||
| public class GitChangesetConverterFactory { | ||||
|  | ||||
|   private final GPG gpg; | ||||
|  | ||||
|   @Inject | ||||
|   public GitChangesetConverterFactory(GPG gpg) { | ||||
|     this.gpg = gpg; | ||||
|   } | ||||
|  | ||||
|   public GitChangesetConverter create(Repository repository) { | ||||
|     return new GitChangesetConverter(repository); | ||||
|     return new GitChangesetConverter(gpg, repository, new RevWalk(repository)); | ||||
|   } | ||||
|  | ||||
|   public GitChangesetConverter create(Repository repository, RevWalk revWalk) { | ||||
|     return new GitChangesetConverter(repository, revWalk); | ||||
|     return new GitChangesetConverter(gpg, repository, revWalk); | ||||
|   } | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user