fix review findings

This commit is contained in:
Konstantin Schaper
2020-12-01 15:16:55 +01:00
parent e8044747e3
commit 9ec8b4efac
17 changed files with 176 additions and 242 deletions

View File

@@ -31,6 +31,7 @@ import lombok.ToString;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.regex.Pattern;
/** /**
* Represents a tag in a repository. * Represents a tag in a repository.
@@ -43,6 +44,9 @@ import java.util.Optional;
@Getter @Getter
public final class Tag { public final class Tag {
public static final String VALID_REV = "[0-9a-z]+";
public static final Pattern VALID_REV_PATTERN = Pattern.compile(VALID_REV);
private final String name; private final String name;
private final String revision; private final String revision;
private final Long date; private final Long date;

View File

@@ -29,29 +29,52 @@ import sonia.scm.repository.spi.TagCommand;
import java.io.IOException; import java.io.IOException;
public class TagCommandBuilder { /**
* @since 2.11.0
*/
public final class TagCommandBuilder {
private final TagCommand command; private final TagCommand command;
public TagCommandBuilder(TagCommand command) { public TagCommandBuilder(TagCommand command) {
this.command = command; this.command = command;
} }
/**
* Initialize a command to tag a revision.
*
* Set parameters and call {@link TagCreateCommandBuilder#execute()}.
*
* @since 2.11.0
*/
public TagCreateCommandBuilder create() { public TagCreateCommandBuilder create() {
return new TagCreateCommandBuilder(); return new TagCreateCommandBuilder();
} }
/**
* Initialize a command to delete a tag.
*
* Set parameters and call {@link TagDeleteCommandBuilder#execute()}.
*
* @since 2.11.0
*/
public TagDeleteCommandBuilder delete() { public TagDeleteCommandBuilder delete() {
return new TagDeleteCommandBuilder(); return new TagDeleteCommandBuilder();
} }
public class TagCreateCommandBuilder { public final class TagCreateCommandBuilder {
private final TagCreateRequest request = new TagCreateRequest(); private final TagCreateRequest request = new TagCreateRequest();
/**
* @param revision The revision identifier for which to create the tag
*/
public TagCreateCommandBuilder setRevision(String revision) { public TagCreateCommandBuilder setRevision(String revision) {
request.setRevision(revision); request.setRevision(revision);
return this; return this;
} }
/**
* @param name The name of the tag
*/
public TagCreateCommandBuilder setName(String name) { public TagCreateCommandBuilder setName(String name) {
request.setName(name); request.setName(name);
return this; return this;
@@ -62,9 +85,12 @@ public class TagCommandBuilder {
} }
} }
public class TagDeleteCommandBuilder { public final class TagDeleteCommandBuilder {
private final TagDeleteRequest request = new TagDeleteRequest(); private final TagDeleteRequest request = new TagDeleteRequest();
/**
* @param name The name of the tag that should be deleted
*/
public TagDeleteCommandBuilder setName(String name) { public TagDeleteCommandBuilder setName(String name) {
request.setName(name); request.setName(name);
return this; return this;

View File

@@ -246,11 +246,9 @@ public abstract class RepositoryServiceProvider implements Closeable
throw new CommandNotSupportedException(Command.TAGS); throw new CommandNotSupportedException(Command.TAGS);
} }
/** /**
* Method description * @since 2.11.0
*
*
* @return
*/ */
public TagCommand getTagCommand() public TagCommand getTagCommand()
{ {

View File

@@ -82,60 +82,16 @@ import static java.util.Optional.of;
public final class GitUtil { public final class GitUtil {
private static final GitUserAgentProvider GIT_USER_AGENT_PROVIDER = new GitUserAgentProvider(); private static final GitUserAgentProvider GIT_USER_AGENT_PROVIDER = new GitUserAgentProvider();
/**
* Field description
*/
public static final String REF_HEAD = "HEAD"; public static final String REF_HEAD = "HEAD";
/**
* Field description
*/
public static final String REF_HEAD_PREFIX = "refs/heads/"; public static final String REF_HEAD_PREFIX = "refs/heads/";
/**
* Field description
*/
public static final String REF_MASTER = "master"; public static final String REF_MASTER = "master";
/**
* Field description
*/
private static final String DIRECTORY_DOTGIT = ".git"; private static final String DIRECTORY_DOTGIT = ".git";
/**
* Field description
*/
private static final String DIRECTORY_OBJETCS = "objects"; private static final String DIRECTORY_OBJETCS = "objects";
/**
* Field description
*/
private static final String DIRECTORY_REFS = "refs"; private static final String DIRECTORY_REFS = "refs";
/**
* Field description
*/
private static final String PREFIX_HEADS = "refs/heads/"; private static final String PREFIX_HEADS = "refs/heads/";
/**
* Field description
*/
private static final String PREFIX_TAG = "refs/tags/"; private static final String PREFIX_TAG = "refs/tags/";
/**
* Field description
*/
private static final String REFSPEC = "+refs/heads/*:refs/remote/scm/%s/*"; private static final String REFSPEC = "+refs/heads/*:refs/remote/scm/%s/*";
/**
* Field description
*/
private static final String REMOTE_REF = "refs/remote/scm/%s/%s"; private static final String REMOTE_REF = "refs/remote/scm/%s/%s";
/**
* Field description
*/
private static final int TIMEOUT = 5; private static final int TIMEOUT = 5;
/** /**
@@ -145,19 +101,11 @@ public final class GitUtil {
//~--- constructors --------------------------------------------------------- //~--- constructors ---------------------------------------------------------
/**
* Constructs ...
*/
private GitUtil() { private GitUtil() {
} }
//~--- methods -------------------------------------------------------------- //~--- methods --------------------------------------------------------------
/**
* Method description
*
* @param repo
*/
public static void close(org.eclipse.jgit.lib.Repository repo) { public static void close(org.eclipse.jgit.lib.Repository repo) {
if (repo != null) { if (repo != null) {
repo.close(); repo.close();
@@ -186,7 +134,7 @@ public final class GitUtil {
if (c != null) { if (c != null) {
tags.put(c.getId(), e.getKey()); tags.put(c.getId(), e.getKey());
} else if (logger.isWarnEnabled()) { } else {
logger.warn("could not find commit for tag {}", e.getKey()); logger.warn("could not find commit for tag {}", e.getKey());
} }
@@ -214,13 +162,6 @@ public final class GitUtil {
} }
} }
/**
* Method description
*
* @param directory
* @return
* @throws IOException
*/
public static org.eclipse.jgit.lib.Repository open(File directory) public static org.eclipse.jgit.lib.Repository open(File directory)
throws IOException { throws IOException {
FS fs = FS.DETECTED; FS fs = FS.DETECTED;
@@ -239,33 +180,18 @@ public final class GitUtil {
return builder.build(); return builder.build();
} }
/**
* Method description
*
* @param formatter
*/
public static void release(DiffFormatter formatter) { public static void release(DiffFormatter formatter) {
if (formatter != null) { if (formatter != null) {
formatter.close(); formatter.close();
} }
} }
/**
* Method description
*
* @param walk
*/
public static void release(TreeWalk walk) { public static void release(TreeWalk walk) {
if (walk != null) { if (walk != null) {
walk.close(); walk.close();
} }
} }
/**
* Method description
*
* @param walk
*/
public static void release(RevWalk walk) { public static void release(RevWalk walk) {
if (walk != null) { if (walk != null) {
walk.close(); walk.close();
@@ -274,12 +200,6 @@ public final class GitUtil {
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/**
* Method description
*
* @param ref
* @return
*/
public static String getBranch(Ref ref) { public static String getBranch(Ref ref) {
String branch = null; String branch = null;
@@ -290,12 +210,6 @@ public final class GitUtil {
return branch; return branch;
} }
/**
* Method description
*
* @param name
* @return
*/
public static String getBranch(String name) { public static String getBranch(String name) {
String branch = null; String branch = null;

View File

@@ -25,6 +25,7 @@
package sonia.scm.repository.spi; package sonia.scm.repository.spi;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import org.apache.shiro.SecurityUtils;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
@@ -34,6 +35,7 @@ import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
import sonia.scm.NotFoundException;
import sonia.scm.event.ScmEventBus; import sonia.scm.event.ScmEventBus;
import sonia.scm.repository.GitUtil; import sonia.scm.repository.GitUtil;
import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.InternalRepositoryException;
@@ -41,7 +43,6 @@ import sonia.scm.repository.PostReceiveRepositoryHookEvent;
import sonia.scm.repository.PreReceiveRepositoryHookEvent; import sonia.scm.repository.PreReceiveRepositoryHookEvent;
import sonia.scm.repository.RepositoryHookEvent; import sonia.scm.repository.RepositoryHookEvent;
import sonia.scm.repository.RepositoryHookType; import sonia.scm.repository.RepositoryHookType;
import sonia.scm.repository.Signature;
import sonia.scm.repository.Tag; import sonia.scm.repository.Tag;
import sonia.scm.repository.api.HookContext; import sonia.scm.repository.api.HookContext;
import sonia.scm.repository.api.HookContextFactory; import sonia.scm.repository.api.HookContextFactory;
@@ -50,6 +51,7 @@ import sonia.scm.repository.api.HookTagProvider;
import sonia.scm.repository.api.TagCreateRequest; import sonia.scm.repository.api.TagCreateRequest;
import sonia.scm.repository.api.TagDeleteRequest; import sonia.scm.repository.api.TagDeleteRequest;
import sonia.scm.security.GPG; import sonia.scm.security.GPG;
import sonia.scm.user.User;
import javax.inject.Inject; import javax.inject.Inject;
import java.io.IOException; import java.io.IOException;
@@ -76,53 +78,72 @@ public class GitTagCommand extends AbstractGitCommand implements TagCommand {
@Override @Override
public Tag create(TagCreateRequest request) { public Tag create(TagCreateRequest request) {
try (Git git = new Git(context.open())) { final String name = request.getName();
String revision = request.getRevision(); final String revision = request.getRevision();
RevObject revObject;
Long tagTime;
if (Strings.isNullOrEmpty(revision)) { if (Strings.isNullOrEmpty(revision)) {
throw new IllegalArgumentException("Revision is required"); throw new IllegalArgumentException("Revision is required");
} }
if (Strings.isNullOrEmpty(name)) {
throw new IllegalArgumentException("Name is required");
}
try (Git git = new Git(context.open())) {
RevObject revObject;
Long tagTime;
ObjectId taggedCommitObjectId = git.getRepository().resolve(revision); ObjectId taggedCommitObjectId = git.getRepository().resolve(revision);
if (taggedCommitObjectId == null) {
throw new NotFoundException("revision", revision);
}
try (RevWalk walk = new RevWalk(git.getRepository())) { try (RevWalk walk = new RevWalk(git.getRepository())) {
revObject = walk.parseAny(taggedCommitObjectId); revObject = walk.parseAny(taggedCommitObjectId);
tagTime = GitUtil.getTagTime(walk, taggedCommitObjectId); tagTime = GitUtil.getTagTime(walk, taggedCommitObjectId);
} }
Tag tag = new Tag(request.getName(), revision, tagTime); Tag tag = new Tag(name, revision, tagTime);
RepositoryHookEvent hookEvent = createTagHookEvent(TagHookContextProvider.createHookEvent(tag)); RepositoryHookEvent hookEvent = createTagHookEvent(TagHookContextProvider.createHookEvent(tag));
eventBus.post(new PreReceiveRepositoryHookEvent(hookEvent)); eventBus.post(new PreReceiveRepositoryHookEvent(hookEvent));
Ref ref = User user = SecurityUtils.getSubject().getPrincipals().oneByType(User.class);
PersonIdent taggerIdent = new PersonIdent(user.getDisplayName(), user.getMail());
// Ref ref =
git.tag() git.tag()
.setObjectId(revObject) .setObjectId(revObject)
.setTagger(new PersonIdent("SCM-Manager", "noreply@scm-manager.org")) .setTagger(taggerIdent)
.setName(request.getName()) .setName(name)
.call(); .call();
try (RevWalk walk = new RevWalk(git.getRepository())) { // Uncomment lines once jgit added support for signing tags
revObject = walk.parseTag(ref.getObjectId()); // try (RevWalk walk = new RevWalk(git.getRepository())) {
final Optional<Signature> tagSignature = GitUtil.getTagSignature(revObject, gpg, walk); // revObject = walk.parseTag(ref.getObjectId());
tagSignature.ifPresent(tag::addSignature); // final Optional<Signature> tagSignature = GitUtil.getTagSignature(revObject, gpg, walk);
} // tagSignature.ifPresent(tag::addSignature);
// }
eventBus.post(new PostReceiveRepositoryHookEvent(hookEvent)); eventBus.post(new PostReceiveRepositoryHookEvent(hookEvent));
return tag; return tag;
} catch (IOException | GitAPIException ex) { } catch (IOException | GitAPIException ex) {
throw new InternalRepositoryException(repository, "could not create tag " + request.getName(), ex); throw new InternalRepositoryException(repository, "could not create tag " + name + " for revision " + revision, ex);
} }
} }
@Override @Override
public void delete(TagDeleteRequest request) { public void delete(TagDeleteRequest request) {
try (Git git = new Git(context.open())) {
String name = request.getName(); String name = request.getName();
if (Strings.isNullOrEmpty(name)) {
throw new IllegalArgumentException("Name is required");
}
try (Git git = new Git(context.open())) {
final Repository repository = git.getRepository(); final Repository repository = git.getRepository();
Optional<Ref> tagRef = findTagRef(git, name); Optional<Ref> tagRef = findTagRef(git, name);
Tag tag; Tag tag;
@@ -135,7 +156,7 @@ public class GitTagCommand extends AbstractGitCommand implements TagCommand {
try (RevWalk walk = new RevWalk(repository)) { try (RevWalk walk = new RevWalk(repository)) {
final RevCommit commit = GitUtil.getCommit(repository, walk, tagRef.get()); final RevCommit commit = GitUtil.getCommit(repository, walk, tagRef.get());
Long tagTime = GitUtil.getTagTime(walk, commit.toObjectId()); Long tagTime = GitUtil.getTagTime(walk, tagRef.get().getObjectId());
tag = new Tag(name, commit.name(), tagTime); tag = new Tag(name, commit.name(), tagTime);
} }
@@ -144,7 +165,7 @@ public class GitTagCommand extends AbstractGitCommand implements TagCommand {
git.tagDelete().setTags(name).call(); git.tagDelete().setTags(name).call();
eventBus.post(new PostReceiveRepositoryHookEvent(hookEvent)); eventBus.post(new PostReceiveRepositoryHookEvent(hookEvent));
} catch (GitAPIException | IOException e) { } catch (GitAPIException | IOException e) {
throw new InternalRepositoryException(repository, "could not delete tag", e); throw new InternalRepositoryException(repository, "could not delete tag " + name, e);
} }
} }
@@ -177,7 +198,7 @@ public class GitTagCommand extends AbstractGitCommand implements TagCommand {
@Override @Override
public Set<HookFeature> getSupportedFeatures() { public Set<HookFeature> getSupportedFeatures() {
return singleton(HookFeature.BRANCH_PROVIDER); return singleton(HookFeature.TAG_PROVIDER);
} }
@Override @Override

View File

@@ -31,7 +31,10 @@ import com.google.common.collect.Lists;
import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.errors.IncorrectObjectTypeException; import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject; import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag; import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk; import org.eclipse.jgit.revwalk.RevWalk;
@@ -76,15 +79,13 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand {
RevWalk revWalk = null; RevWalk revWalk = null;
try { try (Git git = new Git(open())) {
final Git git = new Git(open());
revWalk = new RevWalk(git.getRepository()); revWalk = new RevWalk(git.getRepository());
List<Ref> tagList = git.tagList().call(); List<Ref> tagList = git.tagList().call();
tags = Lists.transform(tagList, tags = Lists.transform(tagList,
new TransformFunction(git.getRepository(), revWalk, gpg, git)); new TransformFunction(git.getRepository(), revWalk, gpg));
} catch (GitAPIException ex) { } catch (GitAPIException ex) {
throw new InternalRepositoryException(repository, "could not read tags from repository", ex); throw new InternalRepositoryException(repository, "could not read tags from repository", ex);
} finally { } finally {
@@ -114,18 +115,15 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand {
/** /**
* Constructs ... * Constructs ...
*
* @param repository * @param repository
* @param revWalk * @param revWalk
*/ */
public TransformFunction(org.eclipse.jgit.lib.Repository repository, public TransformFunction(Repository repository,
RevWalk revWalk, RevWalk revWalk,
GPG gpg, GPG gpg) {
Git git) {
this.repository = repository; this.repository = repository;
this.revWalk = revWalk; this.revWalk = revWalk;
this.gpg = gpg; this.gpg = gpg;
this.git = git;
} }
//~--- methods ------------------------------------------------------------ //~--- methods ------------------------------------------------------------
@@ -141,26 +139,17 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand {
Tag tag = null; Tag tag = null;
try { try {
RevObject revObject = GitUtil.getCommit(repository, revWalk, ref); RevCommit revCommit = GitUtil.getCommit(repository, revWalk, ref);
if (revCommit != null) {
if (revObject != null) {
String name = GitUtil.getTagName(ref); String name = GitUtil.getTagName(ref);
tag = new Tag(name, revCommit.getId().name(), GitUtil.getTagTime(revWalk, ref.getObjectId()));
tag = new Tag(name, revObject.getId().name(), GitUtil.getTagTime(revWalk, ref.getObjectId())); RevObject revObject = revWalk.parseAny(ref.getObjectId());
if (revObject.getType() == Constants.OBJ_TAG) {
try { RevTag revTag = (RevTag) revObject;
RevTag revTag = GitUtil.getTag(repository, revWalk, ref); GitUtil.getTagSignature(revTag, gpg, revWalk)
.ifPresent(tag::addSignature);
final Optional<Signature> tagSignature = GitUtil.getTagSignature(revTag, gpg, revWalk);
if (tagSignature.isPresent()) {
tag.addSignature(tagSignature.get());
} }
} catch (IncorrectObjectTypeException e) {
// Ignore because it is a lightweight tag which cannot have signatures
} }
}
} catch (IOException ex) { } catch (IOException ex) {
logger.error("could not get commit for tag", ex); logger.error("could not get commit for tag", ex);
} }
@@ -173,13 +162,12 @@ public class GitTagsCommand extends AbstractGitCommand implements TagsCommand {
/** /**
* Field description * Field description
*/ */
private org.eclipse.jgit.lib.Repository repository; private final org.eclipse.jgit.lib.Repository repository;
/** /**
* Field description * Field description
*/ */
private RevWalk revWalk; private final RevWalk revWalk;
private final GPG gpg; private final GPG gpg;
private final Git git;
} }
} }

View File

@@ -134,8 +134,8 @@ public class GitTagCommandTest extends AbstractGitCommandTestBase {
} }
private Optional<Tag> findTag(GitContext context, String name) throws IOException { private Optional<Tag> findTag(GitContext context, String name) throws IOException {
List<Tag> branches = readTags(context); List<Tag> tags = readTags(context);
return branches.stream().filter(b -> name.equals(b.getName())).findFirst(); return tags.stream().filter(t -> name.equals(t.getName())).findFirst();
} }
private HookContext createMockedContext(InvocationOnMock invocation) { private HookContext createMockedContext(InvocationOnMock invocation) {

View File

@@ -27,6 +27,7 @@ package sonia.scm.repository.spi;
import com.aragost.javahg.Repository; import com.aragost.javahg.Repository;
import com.aragost.javahg.commands.PullCommand; import com.aragost.javahg.commands.PullCommand;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import org.apache.shiro.SecurityUtils;
import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Tag; import sonia.scm.repository.Tag;
import sonia.scm.repository.api.TagCreateRequest; import sonia.scm.repository.api.TagCreateRequest;
@@ -37,6 +38,7 @@ import java.io.IOException;
public class HgTagCommand extends AbstractCommand implements TagCommand { public class HgTagCommand extends AbstractCommand implements TagCommand {
public static final String DEFAULT_BRANCH_NAME = "default";
private final HgWorkingCopyFactory workingCopyFactory; private final HgWorkingCopyFactory workingCopyFactory;
public HgTagCommand(HgCommandContext context, HgWorkingCopyFactory workingCopyFactory) { public HgTagCommand(HgCommandContext context, HgWorkingCopyFactory workingCopyFactory) {
@@ -46,7 +48,7 @@ public class HgTagCommand extends AbstractCommand implements TagCommand {
@Override @Override
public Tag create(TagCreateRequest request) { public Tag create(TagCreateRequest request) {
try (WorkingCopy<Repository, Repository> workingCopy = workingCopyFactory.createWorkingCopy(getContext(), "default")) { try (WorkingCopy<Repository, Repository> workingCopy = workingCopyFactory.createWorkingCopy(getContext(), DEFAULT_BRANCH_NAME)) {
Repository repository = getContext().open(); Repository repository = getContext().open();
String rev = request.getRevision(); String rev = request.getRevision();
if (Strings.isNullOrEmpty(rev)) { if (Strings.isNullOrEmpty(rev)) {
@@ -54,22 +56,22 @@ public class HgTagCommand extends AbstractCommand implements TagCommand {
} }
com.aragost.javahg.commands.TagCommand.on(workingCopy.getWorkingRepository()) com.aragost.javahg.commands.TagCommand.on(workingCopy.getWorkingRepository())
.rev(rev) .rev(rev)
.user("SCM-Manager") .user(SecurityUtils.getSubject().getPrincipal().toString())
.execute(request.getName()); .execute(request.getName());
pullChangesIntoCentralRepository(workingCopy, "default"); pullChangesIntoCentralRepository(workingCopy, DEFAULT_BRANCH_NAME);
return new Tag(request.getName(), rev); return new Tag(request.getName(), rev);
} }
} }
@Override @Override
public void delete(TagDeleteRequest request) { public void delete(TagDeleteRequest request) {
try (WorkingCopy<Repository, Repository> workingCopy = workingCopyFactory.createWorkingCopy(getContext(), "default")) { try (WorkingCopy<Repository, Repository> workingCopy = workingCopyFactory.createWorkingCopy(getContext(), DEFAULT_BRANCH_NAME)) {
com.aragost.javahg.commands.TagCommand.on(workingCopy.getWorkingRepository()) com.aragost.javahg.commands.TagCommand.on(workingCopy.getWorkingRepository())
.user("SCM-Manager") .user(SecurityUtils.getSubject().getPrincipal().toString())
.remove() .remove()
.execute(request.getName()); .execute(request.getName());
pullChangesIntoCentralRepository(workingCopy, "default"); pullChangesIntoCentralRepository(workingCopy, DEFAULT_BRANCH_NAME);
} }
} }

View File

@@ -24,34 +24,15 @@
package sonia.scm.repository.spi; package sonia.scm.repository.spi;
import com.aragost.javahg.commands.PullCommand;
import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import sonia.scm.repository.Tag; import sonia.scm.repository.Tag;
import sonia.scm.repository.api.TagCommandBuilder;
import sonia.scm.repository.work.NoneCachingWorkingCopyPool;
import sonia.scm.repository.work.WorkdirProvider;
import java.io.IOException;
import java.util.List; import java.util.List;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
public class HgTagsCommandTest extends AbstractHgCommandTestBase { public class HgTagsCommandTest extends AbstractHgCommandTestBase {
private SimpleHgWorkingCopyFactory workingCopyFactory;
@Before
public void initWorkingCopyFactory() {
workingCopyFactory = new SimpleHgWorkingCopyFactory(new NoneCachingWorkingCopyPool(new WorkdirProvider())) {
@Override
public void configure(PullCommand pullCommand) {
// we do not want to configure http hooks in this unit test
}
};
}
@Test @Test
public void shouldGetTagDatesCorrectly() { public void shouldGetTagDatesCorrectly() {
HgTagsCommand hgTagsCommand = new HgTagsCommand(cmdContext); HgTagsCommand hgTagsCommand = new HgTagsCommand(cmdContext);
@@ -61,15 +42,4 @@ public class HgTagsCommandTest extends AbstractHgCommandTestBase {
assertThat(tags.get(0).getDate()).contains(1339586381000L); assertThat(tags.get(0).getDate()).contains(1339586381000L);
} }
@Test
public void shouldNotDie() throws IOException {
HgTagCommand hgTagCommand = new HgTagCommand(cmdContext, workingCopyFactory);
new TagCommandBuilder(hgTagCommand).create().setRevision("79b6baf49711").setName("newtag").execute();
HgTagsCommand hgTagsCommand = new HgTagsCommand(cmdContext);
final List<Tag> tags = hgTagsCommand.getTags();
assertThat(tags).isNotEmpty();
}
} }

View File

@@ -91,7 +91,12 @@ const CreateTagModal: FC<Props> = ({ t, onClose, tagCreationLink, existingTagsLi
footer={ footer={
<> <>
<Button action={onClose}>{t("tags.create.cancel")}</Button> <Button action={onClose}>{t("tags.create.cancel")}</Button>
<Button color="success" action={() => createTag()} loading={loading} disabled={!!validationError || newTagName.length === 0}> <Button
color="success"
action={() => createTag()}
loading={loading}
disabled={!!validationError || newTagName.length === 0}
>
{t("tags.create.confirm")} {t("tags.create.confirm")}
</Button> </Button>
</> </>

View File

@@ -33,6 +33,7 @@ type Props = {
tag: Tag; tag: Tag;
baseUrl: string; baseUrl: string;
onDelete: (tag: Tag) => void; onDelete: (tag: Tag) => void;
// deleting: boolean;
}; };
const Created = styled.span` const Created = styled.span`

View File

@@ -98,7 +98,8 @@ const TagTable: FC<Props> = ({ baseUrl, tags, fetchTags }) => {
</thead> </thead>
<tbody>{renderRow()}</tbody> <tbody>{renderRow()}</tbody>
</table> </table>
</>); </>
);
}; };
export default TagTable; export default TagTable;

View File

@@ -60,7 +60,7 @@ const TagsOverview: FC<Props> = ({ repository, baseUrl }) => {
const renderTagsTable = () => { const renderTagsTable = () => {
if (!loading && tags?.length > 0) { if (!loading && tags?.length > 0) {
orderTags(tags); orderTags(tags);
return <TagTable baseUrl={baseUrl} tags={tags} fetchTags={() => fetchTags()} />; return <TagTable baseUrl={baseUrl} tags={tags} fetchTags={fetchTags} />;
} }
return <Notification type="info">{t("tags.overview.noTags")}</Notification>; return <Notification type="info">{t("tags.overview.noTags")}</Notification>;
}; };

View File

@@ -29,16 +29,20 @@ import lombok.Setter;
import org.hibernate.validator.constraints.Length; import org.hibernate.validator.constraints.Length;
import javax.validation.constraints.NotEmpty; import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.Pattern;
import static sonia.scm.repository.Branch.VALID_BRANCH_NAMES;
import static sonia.scm.repository.Tag.VALID_REV;
@Getter @Getter
@Setter @Setter
public class TagRequestDto { public class TagRequestDto {
// TODO: Validate revision via regex @Pattern(regexp = VALID_REV)
@NotEmpty @NotEmpty
@Length(min = 1, max = 100) @Length(min = 1, max = 100)
private String revision; private String revision;
// TODO: Validate name via regex @Pattern(regexp = VALID_BRANCH_NAMES)
@NotEmpty @NotEmpty
@Length(min = 1, max = 100) @Length(min = 1, max = 100)
private String name; private String name;