Skip to content

Commit 3c1fb32

Browse files
committed
Migrate from StartupActivity (obsolete) -> VcsRepositoryMappingListener
Fixes #445
1 parent 61428b8 commit 3c1fb32

File tree

6 files changed

+109
-102
lines changed

6 files changed

+109
-102
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
### Changed
1010
- Upgrading IntelliJ from 2025.1 to 2025.1.1
11+
- Migrate from `StartupActivity` (obsolete) -> `VcsRepositoryMappingListener`
1112

1213
### Deprecated
1314

src/main/java/com/chriscarini/jetbrains/github/issue/navigation/GitHubIssueNavigationStartupActivity.java

Lines changed: 0 additions & 88 deletions
This file was deleted.
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package com.chriscarini.jetbrains.github.issue.navigation;
2+
3+
import com.chriscarini.jetbrains.github.utils.GitHubUri;
4+
import com.chriscarini.jetbrains.github.utils.GitHubUtils;
5+
import com.intellij.dvcs.repo.VcsRepositoryManager;
6+
import com.intellij.dvcs.repo.VcsRepositoryMappingListener;
7+
import com.intellij.openapi.application.ApplicationManager;
8+
import com.intellij.openapi.diagnostic.Logger;
9+
import com.intellij.openapi.project.Project;
10+
import com.intellij.openapi.vcs.IssueNavigationConfiguration;
11+
import com.intellij.openapi.vcs.IssueNavigationLink;
12+
import git4idea.repo.GitRemote;
13+
import git4idea.repo.GitRepositoryImpl;
14+
import org.jetbrains.annotations.NonNls;
15+
import org.jetbrains.annotations.NotNull;
16+
17+
import java.util.Collection;
18+
import java.util.List;
19+
import java.util.stream.Collectors;
20+
import java.util.stream.Stream;
21+
22+
23+
public class GitHubIssueNavigationVcsRepositoryMappingListener implements VcsRepositoryMappingListener {
24+
25+
private static final @NonNls Logger LOG = Logger.getInstance(GitHubIssueNavigationVcsRepositoryMappingListener.class);
26+
private final @NotNull Project project;
27+
28+
public GitHubIssueNavigationVcsRepositoryMappingListener(@NotNull final Project project) {
29+
this.project = project;
30+
}
31+
32+
@Override
33+
public void mappingChanged() {
34+
35+
if (ApplicationManager.getApplication().isUnitTestMode()) {
36+
LOG.debug("Unit test mode; will not attempt to add GitHub Issue Navigation to project");
37+
return;
38+
}
39+
VcsRepositoryManager.getInstance(project).getRepositories().forEach(repository -> {
40+
final Collection<GitRemote> repoRemotes = ((GitRepositoryImpl) repository).getRemotes();
41+
repoRemotes.forEach(
42+
gitRemote -> {
43+
final String url = gitRemote.getFirstUrl();
44+
45+
if (url == null) {
46+
LOG.debug(String.format("Null Git remote URL: %s", gitRemote));
47+
return;
48+
}
49+
50+
if (!GitHubUtils.isKnownGitHubDomain(url)) {
51+
LOG.debug(String.format(
52+
"Git remote URL (%s) not from a known GitHub domain: %s",
53+
gitRemote,
54+
GitHubUtils.knownGitHubDomains().collect(Collectors.joining(", "))
55+
));
56+
return;
57+
}
58+
59+
final String cleanedUrl = GitHubUri.parseUrl(url).asHttpsFormatUrl();
60+
61+
if (existsInIssueNavConfig(project, cleanedUrl)) {
62+
LOG.debug(String.format("%s is already registered.", cleanedUrl));
63+
return;
64+
}
65+
66+
LOG.debug(String.format("Registering [%s].", cleanedUrl));
67+
addNewIssueNavigationConfiguration(project, cleanedUrl);
68+
}
69+
);
70+
});
71+
}
72+
73+
protected static boolean existsInIssueNavConfig(@NotNull final Project project, @NotNull final String url) {
74+
final List<IssueNavigationLink> matching = IssueNavigationConfiguration.getInstance(project).getLinks()
75+
.stream()
76+
.filter(issueNavigationLink -> issueNavigationLink.getLinkRegexp().contains(url))
77+
.toList();
78+
79+
return !matching.isEmpty();
80+
}
81+
82+
protected static void addNewIssueNavigationConfiguration(@NotNull final Project project, @NotNull final String url) {
83+
final IssueNavigationConfiguration issueNavigationConfiguration = IssueNavigationConfiguration.getInstance(project);
84+
85+
final IssueNavigationLink newLink = new IssueNavigationLink("\\(#(\\d+)\\)", String.format("%s/issues/$1", url));
86+
87+
issueNavigationConfiguration.setLinks(
88+
Stream.concat(
89+
issueNavigationConfiguration.getLinks().stream(),
90+
Stream.of(newLink)
91+
).collect(Collectors.toList()));
92+
}
93+
}

src/main/java/com/chriscarini/jetbrains/github/utils/GitHubUtils.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ public static Stream<String> knownGitHubDomains() {
1919
public static boolean isKnownGitHubDomain(@NotNull final String url) {
2020
final List<String> result = knownGitHubDomains()
2121
.filter(url::contains)
22-
.collect(Collectors.toList());
22+
.toList();
2323

24-
return result.size() > 0;
24+
return !result.isEmpty();
2525
}
2626
}

src/main/resources/META-INF/plugin.xml

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,11 @@
1212
<depends>com.intellij.modules.platform</depends>
1313
<depends>Git4Idea</depends>
1414

15-
<extensions defaultExtensionNs="com.intellij">
16-
17-
<postStartupActivity
18-
implementation="com.chriscarini.jetbrains.github.issue.navigation.GitHubIssueNavigationStartupActivity"/>
19-
20-
</extensions>
15+
<projectListeners>
16+
<listener
17+
class="com.chriscarini.jetbrains.github.issue.navigation.GitHubIssueNavigationVcsRepositoryMappingListener"
18+
topic="com.intellij.dvcs.repo.VcsRepositoryMappingListener"
19+
activeInHeadlessMode="false"
20+
activeInTestMode="false"/>
21+
</projectListeners>
2122
</idea-plugin>

src/test/java/com/chriscarini/jetbrains/github/issue/navigation/TestGitHubIssueNavigationStartupActivityTest.java renamed to src/test/java/com/chriscarini/jetbrains/github/issue/navigation/TestGitHubIssueNavigationVcsRepositoryMappingListenerTest.java

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
import java.util.stream.Collectors;
1111

1212

13-
public class TestGitHubIssueNavigationStartupActivityTest extends LightPlatformTestCase {
13+
public class TestGitHubIssueNavigationVcsRepositoryMappingListenerTest extends LightPlatformTestCase {
1414
@Override
1515
public void setUp() throws Exception {
1616
super.setUp();
@@ -26,25 +26,25 @@ public void testExistsInIssueNavConfig() {
2626
IssueNavigationConfiguration.getInstance(getProject()).setLinks(List.of(myIssueNavigationLink));
2727

2828
// expect
29-
assert GitHubIssueNavigationStartupActivity.existsInIssueNavConfig(getProject(), expectedUrl);
30-
assert !GitHubIssueNavigationStartupActivity.existsInIssueNavConfig(getProject(), unexpectedUrl);
29+
assert GitHubIssueNavigationVcsRepositoryMappingListener.existsInIssueNavConfig(getProject(), expectedUrl);
30+
assert !GitHubIssueNavigationVcsRepositoryMappingListener.existsInIssueNavConfig(getProject(), unexpectedUrl);
3131
}
3232

3333
@Test
3434
public void testAddNewIssueNavigationConfiguration() {
3535
// given
3636
final String expectedUrl = "MY_FAKE_URL";
37-
assert IssueNavigationConfiguration.getInstance(getProject()).getLinks().size() == 0;
37+
assert IssueNavigationConfiguration.getInstance(getProject()).getLinks().isEmpty();
3838

3939
// when
40-
GitHubIssueNavigationStartupActivity.addNewIssueNavigationConfiguration(getProject(), expectedUrl);
40+
GitHubIssueNavigationVcsRepositoryMappingListener.addNewIssueNavigationConfiguration(getProject(), expectedUrl);
4141

4242
// then
4343
final List<IssueNavigationLink> issues = IssueNavigationConfiguration.getInstance(getProject())
4444
.getLinks()
4545
.stream()
4646
.filter(issueNavigationLink -> issueNavigationLink.getLinkRegexp().contains(expectedUrl))
47-
.collect(Collectors.toList());
47+
.toList();
4848
assertEquals(1, issues.size());
4949
}
5050
}

0 commit comments

Comments
 (0)