From e8df735e2729a966fde930d6902779e097ff3867 Mon Sep 17 00:00:00 2001 From: stelios maurommatakis Date: Wed, 30 Oct 2024 13:50:10 +0200 Subject: [PATCH] refactor: Create issue Create issue through cli instead of httpd Signed-off-by: stelios maurommatakis --- .../actions/rad/RadCobShow.java | 3 +- .../actions/rad/RadIssueCreate.java | 37 +++++++++++++++++++ .../commands/LinuxScriptCommand.java | 5 ++- .../commands/RadicleScriptCommand.java | 28 ++++++++++++-- .../commands/RadicleScriptCommandFactory.java | 7 ++-- .../commands/WindowsScriptCommand.java | 6 ++- .../issues/CreateIssuePanel.java | 10 ++--- .../models/RadIssue.java | 4 +- .../services/RadicleCliService.java | 8 ++++ .../services/RadicleProjectService.java | 16 +++++++- .../toolwindow/DragAndDropField.java | 4 +- .../issues/IssueListPanelTest.java | 9 ----- .../issues/OverviewTest.java | 16 +++----- 13 files changed, 110 insertions(+), 43 deletions(-) create mode 100644 src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadIssueCreate.java diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadCobShow.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadCobShow.java index 228bf7617..5c25495cf 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadCobShow.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadCobShow.java @@ -6,7 +6,6 @@ import network.radicle.jetbrains.radiclejetbrainsplugin.models.RadIssue; import network.radicle.jetbrains.radiclejetbrainsplugin.models.RadPatch; import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleCliService; -import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleProjectApi; import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleProjectService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -40,7 +39,7 @@ public RadIssue getIssue() { var json = output.getStdout(); RadIssue issue = null; try { - issue = RadicleProjectApi.MAPPER.readValue(json, new TypeReference<>() { }); + issue = RadicleCliService.MAPPER.readValue(json, new TypeReference<>() { }); var firstDiscussion = issue.discussion.get(0); issue.author = firstDiscussion.author; issue.project = repo.getProject(); diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadIssueCreate.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadIssueCreate.java new file mode 100644 index 000000000..d1f7a2abb --- /dev/null +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/actions/rad/RadIssueCreate.java @@ -0,0 +1,37 @@ +package network.radicle.jetbrains.radiclejetbrainsplugin.actions.rad; + +import com.intellij.execution.process.ProcessOutput; +import git4idea.repo.GitRepository; +import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleProjectService; + +import java.util.List; + +public class RadIssueCreate extends RadAction { + private final String title; + private final String description; + private final List assignees; + private final List labels; + + public RadIssueCreate(GitRepository repo, String title, String description, List assignees, List labels) { + super(repo); + this.title = title; + this.description = description; + this.assignees = assignees; + this.labels = labels; + } + + @Override + public ProcessOutput run() { + var rad = project.getService(RadicleProjectService.class); + return rad.createIssue(repo, title, description, assignees, labels); + } + + @Override + public String getActionName() { + return null; + } + + public boolean shouldUnlockIdentity() { + return true; + } +} diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/LinuxScriptCommand.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/LinuxScriptCommand.java index e2d301989..9073c13cc 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/LinuxScriptCommand.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/LinuxScriptCommand.java @@ -1,11 +1,12 @@ package network.radicle.jetbrains.radiclejetbrainsplugin.commands; import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.openapi.project.Project; import java.util.List; public class LinuxScriptCommand extends RadicleScriptCommand { - public LinuxScriptCommand(String workDir, String exePath, String radHome, List args) { - super(workDir, exePath, radHome, args); + public LinuxScriptCommand(String workDir, String exePath, String radHome, List args, Project project) { + super(workDir, exePath, radHome, args, project); } @Override diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommand.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommand.java index d8dee30ef..6e58cc36a 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommand.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommand.java @@ -1,8 +1,12 @@ package network.radicle.jetbrains.radiclejetbrainsplugin.commands; import com.google.common.base.Charsets; +import com.google.common.base.Strings; import com.intellij.execution.configurations.GeneralCommandLine; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.io.FileUtil; +import network.radicle.jetbrains.radiclejetbrainsplugin.config.RadicleProjectSettingsHandler; +import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleCliService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -24,17 +28,19 @@ public abstract class RadicleScriptCommand { public String exePath; public String shebang; public List args; + public RadicleCliService cliService; - public RadicleScriptCommand(String workDir, String shebang, String exePath, String radHome, List args) { + public RadicleScriptCommand(String workDir, String shebang, String exePath, String radHome, List args, Project project) { this.workDir = workDir; this.shebang = shebang; this.exePath = exePath; this.radHome = radHome; this.args = args; + this.cliService = project.getService(RadicleCliService.class); } - public RadicleScriptCommand(String workDir, String exePath, String radHome, List args) { - this(workDir, "#!/bin/bash", exePath, radHome, args); + public RadicleScriptCommand(String workDir, String exePath, String radHome, List args, Project project) { + this(workDir, "#!/bin/bash", exePath, radHome, args, project); } public File createTempExecutableScript() { @@ -52,7 +58,8 @@ public File createTempExecutableScript() { public String getCommand() { var command = String.join(" ", args); - return shebang + "\n" + getExportRadHomeCommand() + exePath + " " + command; + return shebang + "\n" + getExportRadPassphrase() + + getExportRadHomeCommand() + exePath + " " + command; } public File getTempPath() { @@ -73,6 +80,19 @@ private String getExportRadHomeCommand() { return "export RAD_HOME=" + radHome + "\n"; } + private String getExportRadPassphrase() { + var currentIdentity = cliService.getCurrentIdentity(); + if (currentIdentity == null) { + return ""; + } + var projectSettings = new RadicleProjectSettingsHandler(cliService.getProject()); + var password = projectSettings.getPassword(currentIdentity.nodeId); + if (Strings.isNullOrEmpty(password)) { + return ""; + } + return "export RAD_PASSPHRASE=" + password + "\n"; + } + private String getRandomScriptName() { var randomStr = UUID.randomUUID().toString(); var firstPart = randomStr.split("-")[0]; diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommandFactory.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommandFactory.java index 3c9a08d5d..723ab88ab 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommandFactory.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/RadicleScriptCommandFactory.java @@ -1,5 +1,6 @@ package network.radicle.jetbrains.radiclejetbrainsplugin.commands; +import com.intellij.openapi.project.Project; import com.intellij.openapi.util.SystemInfo; import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleProjectService; @@ -7,11 +8,11 @@ public class RadicleScriptCommandFactory { public static RadicleScriptCommand create(String workDir, String exePath, String radHome, List args, - RadicleProjectService service) { + RadicleProjectService service, Project project) { if (SystemInfo.isWindows) { - return new WindowsScriptCommand(service, workDir, exePath, radHome, args); + return new WindowsScriptCommand(service, workDir, exePath, radHome, args, project); } else { - return new LinuxScriptCommand(workDir, exePath, radHome, args); + return new LinuxScriptCommand(workDir, exePath, radHome, args, project); } } } diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/WindowsScriptCommand.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/WindowsScriptCommand.java index 02afd937c..5f5970b44 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/WindowsScriptCommand.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/commands/WindowsScriptCommand.java @@ -3,6 +3,7 @@ import com.google.common.base.Strings; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.wsl.WSLDistribution; +import com.intellij.openapi.project.Project; import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleProjectService; import java.io.File; @@ -11,8 +12,9 @@ public class WindowsScriptCommand extends RadicleScriptCommand { private final WSLDistribution wslDistribution; - public WindowsScriptCommand(RadicleProjectService service, String workDir, String exePath, String radHome, List args) { - super(workDir, exePath, radHome, args); + public WindowsScriptCommand(RadicleProjectService service, String workDir, String exePath, String radHome, + List args, Project project) { + super(workDir, exePath, radHome, args, project); this.wslDistribution = new WSLDistribution(service.getWslDistro()); } diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/CreateIssuePanel.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/CreateIssuePanel.java index d4d38a146..e84ec53d0 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/CreateIssuePanel.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/CreateIssuePanel.java @@ -58,7 +58,6 @@ public class CreateIssuePanel { private final RadicleProjectApi api; - private final RadicleCliService cli; private final Project project; private AssigneesSelect assigneeSelect; private LabelSelect labelSelect; @@ -68,6 +67,7 @@ public class CreateIssuePanel { private DragAndDropField descriptionField; protected IssueTabController issueTabController; private ComboBox projectSelect; + private final RadicleCliService cliService; public AssigneesSelect getAssigneeSelect() { return assigneeSelect; @@ -80,7 +80,7 @@ public LabelSelect getLabelSelect() { public CreateIssuePanel(IssueTabController issueTabController, Project project) { this.issueTabController = issueTabController; this.api = project.getService(RadicleProjectApi.class); - this.cli = project.getService(RadicleCliService.class); + this.cliService = project.getService(RadicleCliService.class); this.project = project; } @@ -140,7 +140,7 @@ private JComponent infoComponent() { borderPanel.add(projectSelect, BorderLayout.NORTH); borderPanel.add(titleField, BorderLayout.CENTER); - descriptionField = new DragAndDropField(project, 0); + descriptionField = new DragAndDropField(project, 0, false); descriptionField.setBackground(UIUtil.getListBackground()); descriptionField.setFont(JBFont.label()); descriptionField.getComponent().setBorder(JBUI.Borders.empty(8)); @@ -178,8 +178,8 @@ public void actionPerformed(ActionEvent e) { } newIssueButton.setEnabled(false); ApplicationManager.getApplication().executeOnPooledThread(() -> { - var radProject = cli.getRadRepo(repo); - var isSuccess = api.createIssue(issueTitle, issueDescription, assignees, labels, repo, radProject.id, descriptionField.getEmbedList()); + var output = cliService.createIssue(repo, issueTitle, issueDescription, assignees, labels); + var isSuccess = RadAction.isSuccess(output); ApplicationManager.getApplication().invokeLater(() -> { if (isSuccess) { issueTabController.createPanel(); diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/models/RadIssue.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/models/RadIssue.java index d7dd97925..868107d01 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/models/RadIssue.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/models/RadIssue.java @@ -11,7 +11,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.project.Project; import git4idea.repo.GitRepository; -import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleProjectApi; +import network.radicle.jetbrains.radiclejetbrainsplugin.services.RadicleCliService; import java.util.ArrayList; import java.util.Iterator; @@ -107,7 +107,7 @@ public List deserialize(JsonParser jsonParser, DeserializationCon for (Iterator it = comments.fieldNames(); it.hasNext();) { var key = it.next(); var comment = comments.get(key); - var discussion = RadicleProjectApi.MAPPER.readValue(comment.toString(), new TypeReference() { }); + var discussion = RadicleCliService.MAPPER.readValue(comment.toString(), new TypeReference() { }); discussion.id = key; discussions.add(discussion); } diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleCliService.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleCliService.java index 77c240bd0..53bd1c242 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleCliService.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleCliService.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.intellij.execution.process.ProcessOutput; import com.intellij.openapi.project.Project; import git4idea.commands.Git; import git4idea.repo.GitRemote; @@ -12,6 +13,7 @@ import network.radicle.jetbrains.radiclejetbrainsplugin.actions.rad.RadAction; import network.radicle.jetbrains.radiclejetbrainsplugin.actions.rad.RadCobList; import network.radicle.jetbrains.radiclejetbrainsplugin.actions.rad.RadCobShow; +import network.radicle.jetbrains.radiclejetbrainsplugin.actions.rad.RadIssueCreate; import network.radicle.jetbrains.radiclejetbrainsplugin.actions.rad.RadSelf; import network.radicle.jetbrains.radiclejetbrainsplugin.config.RadicleProjectSettingsHandler; import network.radicle.jetbrains.radiclejetbrainsplugin.models.RadAuthor; @@ -44,6 +46,11 @@ public RadicleCliService(Project project) { radRepoIds = new HashMap<>(); } + public ProcessOutput createIssue(GitRepository repo, String title, String description, List assignees, List labels) { + var issueCreate = new RadIssueCreate(repo, title, description, assignees, labels); + return issueCreate.perform(); + } + public RadIssue getIssue(GitRepository repo, String projectId, String objectId) { var cobShow = new RadCobShow(repo, projectId, objectId, RadCobList.Type.ISSUE); return cobShow.getIssue(); @@ -65,6 +72,7 @@ public List getIssues(GitRepository repo, String projectId) { } issues.add(issue); } + issues.sort(Comparator.comparing(issue -> ((RadIssue) issue).discussion.get(0).timestamp).reversed()); return issues; } diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleProjectService.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleProjectService.java index dd9da0d1e..2f0947f51 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleProjectService.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/services/RadicleProjectService.java @@ -381,6 +381,20 @@ private ProcessOutput addRemoveLabels(GitRepository root, String id, List assignees, List labels) { + var labelsStr = labels.stream().map(label -> "--label " + ExecUtil.escapeUnixShellArgument(label)).collect(Collectors.joining(" ")); + var assigneesStr = assignees.stream().map(assignee -> "--assign " + ExecUtil.escapeUnixShellArgument(assignee)).collect(Collectors.joining(" ")); + List params = new ArrayList<>(Arrays.asList("issue", "open", "--title", + ExecUtil.escapeUnixShellArgument(title), "--description", ExecUtil.escapeUnixShellArgument(description))); + if (!Strings.isNullOrEmpty(labelsStr)) { + params.add(labelsStr); + } + if (!Strings.isNullOrEmpty(assigneesStr)) { + params.add(assigneesStr); + } + return executeCommandFromFile(root, params); + } + public ProcessOutput changeIssueState(GitRepository root, String issueId, String state) { return executeCommand(root.getRoot().getPath(), List.of("issue", "state", issueId, state), root); } @@ -422,7 +436,7 @@ public ProcessOutput executeCommandFromFile(GitRepository repo, List par final var radPath = projectSettings.getPath(); final var radHome = projectSettings.getRadHome(); var workDir = repo.getRoot().getPath(); - var scriptCommand = RadicleScriptCommandFactory.create(workDir, radPath, radHome, params, this); + var scriptCommand = RadicleScriptCommandFactory.create(workDir, radPath, radHome, params, this, project); var output = runCommand(scriptCommand.getCommandLine(), repo, workDir, null); scriptCommand.deleteTempFile(); return output; diff --git a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/toolwindow/DragAndDropField.java b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/toolwindow/DragAndDropField.java index 59e2ed1bf..20dbc5420 100644 --- a/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/toolwindow/DragAndDropField.java +++ b/src/main/java/network/radicle/jetbrains/radiclejetbrainsplugin/toolwindow/DragAndDropField.java @@ -50,8 +50,8 @@ public DragAndDropField(Project project, boolean allowDragAndDrop) { this.addDocumentListener(new MyListener(this)); } - public DragAndDropField(Project project, int border) { - this(project, true); + public DragAndDropField(Project project, int border, boolean allowDragAndDrop) { + this(project, allowDragAndDrop); this.border = border; } diff --git a/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/IssueListPanelTest.java b/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/IssueListPanelTest.java index 2b367ae41..1d6906f1b 100644 --- a/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/IssueListPanelTest.java +++ b/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/IssueListPanelTest.java @@ -157,9 +157,6 @@ public void testFilterByProject() throws ExecutionException, InterruptedExceptio var issueModel = listPanel.getModel(); assertThat(issueModel.getSize()).isEqualTo(2); - - var issue = issueModel.get(0); - assertThat(issue.author.id).isEqualTo(issues.get(0).author.id); } @Test @@ -172,12 +169,6 @@ public void testFilterByAssignees() { var issueModel = listPanel.getModel(); assertThat(issueModel.getSize()).isEqualTo(2); - - var issue = issueModel.get(0); - assertThat(issue.id).isEqualTo(issues.get(0).id); - - issue = issueModel.get(1); - assertThat(issue.id).isEqualTo(issues.get(1).id); } @Test diff --git a/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/OverviewTest.java b/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/OverviewTest.java index ef789f81e..a39e9aebe 100644 --- a/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/OverviewTest.java +++ b/src/test/java/network/radicle/jetbrains/radiclejetbrainsplugin/issues/OverviewTest.java @@ -375,17 +375,11 @@ public void createNewIssueTest() throws InterruptedException { var createIssueButton = UIUtil.findComponentOfType(buttonsPanel, JButton.class); createIssueButton.doClick(); executeUiTasks(); - var res = response.poll(10, TimeUnit.SECONDS); - - var embeds = (ArrayList>) res.get("embeds"); - assertThat(embeds.get(0).get("oid")).isEqualTo(dummyEmbed.getOid()); - assertThat(embeds.get(0).get("name")).isEqualTo(dummyEmbed.getName()); - assertThat(embeds.get(0).get("content")).isEqualTo(dummyEmbed.getContent()); - - assertThat(res.get("title")).isEqualTo(ISSUE_NAME); - assertThat(res.get("description")).isEqualTo(issueDescription); - assertThat(res.get("labels")).usingRecursiveAssertion().isEqualTo(List.of(label2)); - assertThat(res.get("assignees")).usingRecursiveAssertion().isEqualTo(List.of(getTestProjects().get(0).delegates.get(0).id)); + var issueCommand = radStub.commandsStr.poll(); + assertThat(issueCommand).contains(ExecUtil.escapeUnixShellArgument(ISSUE_NAME)); + assertThat(issueCommand).contains(ExecUtil.escapeUnixShellArgument(issueDescription)); + assertThat(issueCommand).contains(ExecUtil.escapeUnixShellArgument(label2)); + assertThat(issueCommand).contains(ExecUtil.escapeUnixShellArgument(getTestProjects().get(0).delegates.get(0).id)); } @Test