diff --git a/src/main/java/com/jcabi/github/Releases.java b/src/main/java/com/jcabi/github/Releases.java
index cbff6d13a..eea466ef3 100644
--- a/src/main/java/com/jcabi/github/Releases.java
+++ b/src/main/java/com/jcabi/github/Releases.java
@@ -30,8 +30,11 @@
package com.jcabi.github;
import com.jcabi.aspects.Immutable;
+import com.jcabi.aspects.Loggable;
import java.io.IOException;
import javax.validation.constraints.NotNull;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
/**
* Github Releases.
@@ -86,4 +89,92 @@ Release create(
* @see Delete a release.
*/
void remove(int number) throws IOException;
+
+ /**
+ * Smart releases.
+ * @since 0.17
+ */
+ @Immutable
+ @ToString
+ @Loggable(Loggable.DEBUG)
+ @EqualsAndHashCode(of = "releases")
+ final class Smart implements Releases {
+ /**
+ * Encapsulated releases.
+ */
+ private final transient Releases releases;
+
+ /**
+ * Public CTOR.
+ * @param original Original releases
+ */
+ public Smart(
+ @NotNull(message = "original can't be NULL") final Releases original
+ ) {
+ this.releases = original;
+ }
+ @Override
+ public Repo repo() {
+ return this.releases.repo();
+ }
+ @Override
+ public Iterable iterate() {
+ return this.releases.iterate();
+ }
+ @Override
+ public Release get(final int number) {
+ return this.releases.get(number);
+ }
+ @Override
+ public Release create(final String tag) throws IOException {
+ return this.releases.create(tag);
+ }
+ @Override
+ public void remove(final int number) throws IOException {
+ this.releases.remove(number);
+ }
+ /**
+ * This release exists by the tag.
+ * @param tag The tag
+ * @return TRUE if it already exists
+ * @throws IOException If fails
+ */
+ public boolean exists(final String tag) throws IOException {
+ boolean exists = false;
+ final Iterable rels = new Smarts(
+ this.iterate()
+ );
+ for (final Release.Smart rel : rels) {
+ if (rel.tag().equals(tag)) {
+ exists = true;
+ break;
+ }
+ }
+ return exists;
+ }
+ /**
+ * Find release by the tag (runtime exception if not found).
+ * @param tag The tag
+ * @return Release found
+ * @throws IOException If fails
+ */
+ public Release find(final String tag) throws IOException {
+ Release found = null;
+ final Iterable rels = new Smarts(
+ this.iterate()
+ );
+ for (final Release.Smart rel : rels) {
+ if (rel.tag().equals(tag)) {
+ found = rel;
+ break;
+ }
+ }
+ if (found == null) {
+ throw new IllegalArgumentException(
+ String.format("release not found by tag '%s'", tag)
+ );
+ }
+ return found;
+ }
+ }
}
diff --git a/src/test/java/com/jcabi/github/mock/MkReleasesTest.java b/src/test/java/com/jcabi/github/mock/MkReleasesTest.java
index b0d8642f8..59af31bb3 100644
--- a/src/test/java/com/jcabi/github/mock/MkReleasesTest.java
+++ b/src/test/java/com/jcabi/github/mock/MkReleasesTest.java
@@ -133,6 +133,25 @@ public void canRemoveRelease() throws Exception {
);
}
+ /**
+ * MkReleases can find release by tag.
+ * @throws Exception If some problem inside
+ */
+ @Test
+ public void findsReleaseByTag() throws Exception {
+ final Releases releases = MkReleasesTest.repo().releases();
+ final String tag = "v5.0";
+ releases.create(tag);
+ MatcherAssert.assertThat(
+ new Releases.Smart(releases).exists(tag),
+ Matchers.is(true)
+ );
+ MatcherAssert.assertThat(
+ new Release.Smart(new Releases.Smart(releases).find(tag)).tag(),
+ Matchers.equalTo(tag)
+ );
+ }
+
/**
* Create a repo to work with.
* @return Repo