pl.project13.jgit.DescribeResult Maven / Gradle / Ivy
Show all versions of git-commit-id-plugin Show documentation
/*
* This file is part of git-commit-id-plugin by Konrad 'ktoso' Malawski
*
* git-commit-id-plugin is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* git-commit-id-plugin is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with git-commit-id-plugin. If not, see .
*/
package pl.project13.jgit;
import com.google.common.base.Preconditions;
import java.io.IOException;
import java.util.*;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
/**
* Represents the result of a git describe
command.
*
* See {@link pl.project13.jgit.DescribeResult#toString()} for a detailed information how this result looks like.
*/
public class DescribeResult {
private Optional tagName = Optional.empty();
private Optional commitId = Optional.empty();
private Optional abbreviatedObjectId = Optional.empty();
private int abbrev = 7;
private int commitsAwayFromTag;
private boolean dirty;
private String dirtyMarker;
private boolean forceLongFormat;
private ObjectReader objectReader;
public static final DescribeResult EMPTY = new DescribeResult("");
public DescribeResult(@Nonnull String tagName) {
this(tagName, false, Optional.empty());
}
public DescribeResult(@Nonnull ObjectReader objectReader, String tagName, int commitsAwayFromTag, @Nonnull ObjectId commitId) {
this(objectReader, tagName, commitsAwayFromTag, commitId, false, Optional.empty(), false);
}
public DescribeResult(@Nonnull ObjectReader objectReader, @Nonnull ObjectId commitId) {
this.objectReader = objectReader;
this.commitId = Optional.of(commitId);
this.abbreviatedObjectId = createAbbreviatedCommitId(objectReader, commitId, this.abbrev);
}
public DescribeResult(@Nonnull ObjectReader objectReader, String tagName, int commitsAwayFromTag, ObjectId commitId, boolean dirty, String dirtyMarker) {
this(objectReader, tagName, commitsAwayFromTag, commitId, dirty, Optional.of(dirtyMarker), false);
}
public DescribeResult(@Nonnull ObjectReader objectReader, String tagName, int commitsAwayFromTag, ObjectId commitId, boolean dirty, Optional dirtyMarker, boolean forceLongFormat) {
this(objectReader, commitId, dirty, dirtyMarker);
this.tagName = Optional.of(tagName);
this.commitsAwayFromTag = commitsAwayFromTag;
this.forceLongFormat = forceLongFormat;
}
public DescribeResult(@Nonnull ObjectReader objectReader, @Nonnull ObjectId commitId, boolean dirty, @Nonnull Optional dirtyMarker) {
this.objectReader = objectReader;
this.commitId = Optional.of(commitId);
this.abbreviatedObjectId = createAbbreviatedCommitId(objectReader, commitId, this.abbrev);
this.dirty = dirty;
this.dirtyMarker = dirtyMarker.orElse("");
}
public DescribeResult(@Nonnull String tagName, boolean dirty, @Nonnull Optional dirtyMarker) {
this.tagName = Optional.of(tagName);
this.dirty = dirty;
this.dirtyMarker = dirtyMarker.orElse("");
}
@Nonnull
public DescribeResult withCommitIdAbbrev(int n) {
Preconditions.checkArgument(n >= 0, String.format("The --abbrev parameter must be >= 0, but it was: [%s]", n));
this.abbrev = n;
this.abbreviatedObjectId = createAbbreviatedCommitId(this.objectReader, this.commitId.get(), this.abbrev);
return this;
}
/**
* The format of a describe result is defined as:
*
* v1.0.4-14-g2414721-DEV
* ^ ^ ^ ^
* | | | |-- if a dirtyMarker was given, it will appear here if the repository is in "dirty" state
* | | |---------- the "g" prefixed commit id. The prefix is compatible with what git-describe would return - weird, but true.
* | |--------------- the number of commits away from the found tag. So "2414721" is 14 commits ahead of "v1.0.4", in this example.
* |-------------------- the "nearest" tag, to the mentioned commit.
*
*
* Other outputs may look like:
*
* v1.0.4 -- if the repository is "on a tag"
* v1.0.4-DEV -- if the repository is "on a tag", but in "dirty" state
* 2414721 -- a plain commit id hash if not tags were defined (of determined "near" this commit).
* It does NOT include the "g" prefix, that is used in the "full" describe output format!
*
*
* For more details (on when what output will be returned etc), see man git-describe
.
* In general, you can assume it's a "best effort" approach, to give you as much info about the repo state as possible.
*
* @return the String representation of this Describe command
*/
@Override
public String toString() {
List parts;
if (abbrevZeroHidesCommitsPartOfDescribe()) {
parts = new ArrayList<>(Collections.singletonList(tag()));
} else {
parts = new ArrayList<>(Arrays.asList(tag(), commitsAwayFromTag(), prefixedCommitId()));
}
final StringJoiner sj = new StringJoiner("-");
parts.stream().filter(Objects::nonNull).forEach(sj::add);
return sj.toString() + dirtyMarker(); // like in the describe spec the entire "-dirty" is configurable (incl. "-")
}
private boolean abbrevZeroHidesCommitsPartOfDescribe() {
return abbrev == 0;
}
@Nullable
public String commitsAwayFromTag() {
if (forceLongFormat) {
return String.valueOf(commitsAwayFromTag);
}
return commitsAwayFromTag == 0 ? null : String.valueOf(commitsAwayFromTag);
}
@Nullable
public String dirtyMarker() {
return dirty ? dirtyMarker : "";
}
/**
* The (possibly) "g" prefixed abbreviated object id of a commit.
*
* The "g" prefix is prepended to be compatible with git's describe output, please refer to
* man git-describe to check why it's included.
*
*
* The "g" prefix is used when a tag is defined on this result. If it's not, this method yields a plain commit id hash.
* This is following git's behaviour - so any git tooling should be happy with this output.
*
*
* Notes about the abbreviated object id:
* Git will try to use your given abbrev length, but when it's too short to guarantee uniqueness -
* a longer one will be used (which WILL guarantee uniqueness).
* If you need the full commit id, it's always available via {@link pl.project13.jgit.DescribeResult#commitObjectId()}.
*
*/
@Nullable
public String prefixedCommitId() {
if (abbreviatedObjectId.isPresent()) {
String name = abbreviatedObjectId.get().name();
return gPrefixedCommitId(name);
} else if (commitId.isPresent()) {
String name = commitId.get().name();
return gPrefixedCommitId(name);
} else {
return null;
}
}
private String gPrefixedCommitId(String name) {
if (tagName.isPresent()) {
return "g" + name;
} else {
return name;
}
}
/**
* JGit won't ever use 1 char as abbreviated ID, that's why only values of:
*
* - 0 (special meaning - don't show commit id at all),
* - the range from 2 to 40 (inclusive) are valid
*
*
* @return the abbreviated commit id, possibly longer than the requested len (if it wouldn't be unique)
*/
private static Optional createAbbreviatedCommitId(@Nonnull ObjectReader objectReader, ObjectId commitId, int requestedLength) {
if (requestedLength < 2) {
// 0 means we don't want to print commit id's at all
return Optional.empty();
}
try {
AbbreviatedObjectId abbreviatedObjectId = objectReader.abbreviate(commitId, requestedLength);
return Optional.of(abbreviatedObjectId);
} catch (IOException e) {
return Optional.empty();
}
}
@Nullable
public ObjectId commitObjectId() {
if (commitId.isPresent()) {
return commitId.get();
} else {
return null;
}
}
@Nullable
public String tag() {
return tagName.orElse(null);
}
}