Skip to content

Commit 1e44a8f

Browse files
committed
Merge branch '2025.2' into 2025.3
2 parents 7258d21 + 338eef2 commit 1e44a8f

File tree

16 files changed

+384
-69
lines changed

16 files changed

+384
-69
lines changed

changelog.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# Minecraft Development for IntelliJ
22

3+
## [1.8.10]
4+
5+
### Fixed
6+
7+
- Fixed `transitive-*` being reported as an error in class tweakers.
8+
- Fixed all local classes being reported as being inside a mixin.
9+
- Fixed write-unsafe context errors when using the project creator.
10+
311
## [1.8.9]
412

513
### Fixed

create_release.py

Lines changed: 242 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,242 @@
1+
#!/usr/bin/env python3
2+
"""
3+
create_release.py
4+
5+
Usage:
6+
python create_release.py <version> [--branches 2024.3 2025.1 ...] [--dry-run]
7+
8+
Example:
9+
python create_release.py 1.2.3
10+
python create_release.py 1.2.3 --branches 2024.3 2025.1 2025.2 2025.3
11+
python create_release.py 1.2.3 --dry-run
12+
"""
13+
14+
from __future__ import annotations
15+
import argparse
16+
import shlex
17+
import subprocess
18+
import sys
19+
from typing import List, Tuple
20+
21+
BRANCHES=["2024.3", "2025.1", "2025.2", "2025.3"]
22+
23+
def check_file_contains_version(path: str, version: str) -> bool:
24+
try:
25+
with open(path, "r") as fh:
26+
data = fh.read()
27+
except Exception as e:
28+
print(f"Unable to read file {path}: {e}", file=sys.stderr)
29+
return False
30+
return version in data
31+
32+
def sanity_check_file_versions(version: str) -> bool:
33+
result = True
34+
for path in ["readme.md", "changelog.md", "gradle.properties"]:
35+
if not check_file_contains_version(path, version):
36+
print(f"File {path} does not contain the version number")
37+
result = False
38+
return result
39+
40+
def run_git(args: List[str], dry_run: bool = False, capture_output: bool = True) -> Tuple[int, str, str]:
41+
"""Run git command and return (returncode, stdout, stderr)."""
42+
if dry_run:
43+
print(f"[dry_run] would: git {" ".join(args)}")
44+
return 0, "", ""
45+
46+
proc = subprocess.run(
47+
["git"] + args,
48+
stdout=subprocess.PIPE if capture_output else None,
49+
stderr=subprocess.PIPE if capture_output else None,
50+
text=True,
51+
shell=False,
52+
)
53+
stdout = proc.stdout or ""
54+
stderr = proc.stderr or ""
55+
return proc.returncode, stdout.strip(), stderr.strip()
56+
57+
def working_tree_clean() -> bool:
58+
rc, out, _ = run_git(["status", "--porcelain"])
59+
return out.strip() == ""
60+
61+
def ensure_branch_local_or_origin(branch: str, dry_run: bool):
62+
# if local branch exists, do nothing
63+
rc, _, _ = run_git(["show-ref", "--verify", f"refs/heads/{branch}"])
64+
if rc == 0:
65+
return
66+
# local branch not present, check origin/<branch>
67+
rc, _, _ = run_git(["ls-remote", "--exit-code", "--heads", "origin", branch])
68+
if rc == 0:
69+
print(f"Creating local branch '{branch}' from origin/{branch}...")
70+
rc2, out, err = run_git(["checkout", "-b", branch, f"origin/{branch}"], dry_run, capture_output=True)
71+
if dry_run:
72+
return
73+
if rc2 != 0:
74+
print(f"Failed to create local branch {branch} from origin/{branch}.", file=sys.stderr)
75+
print(out, err, sep="\n", file=sys.stderr)
76+
sys.exit(1)
77+
return
78+
# neither local nor origin branch exists
79+
print(f"Branch '{branch}' does not exist locally nor on origin. Aborting.", file=sys.stderr)
80+
sys.exit(1)
81+
82+
def checkout_branch(branch: str, dry_run: bool):
83+
rc, out, err = run_git(["checkout", branch], dry_run)
84+
if dry_run:
85+
return
86+
if rc != 0:
87+
print(f"Failed to checkout branch '{branch}'.", file=sys.stderr)
88+
print(out, err, sep="\n", file=sys.stderr)
89+
sys.exit(1)
90+
91+
def pull_ff_only(branch: str, dry_run: bool):
92+
# Try to fast-forward only; if it fails, continue (we don't forcibly rebase here).
93+
rc, out, err = run_git(["pull", "--ff-only", "origin", branch], dry_run)
94+
if dry_run:
95+
return
96+
# It's fine if pull reports nothing to do (rc==0) or fails (rc != 0); we'll continue,
97+
# but if rc != 0 we print a helpful message.
98+
if rc != 0:
99+
print(f"Warning: 'git pull --ff-only origin {branch}' returned non-zero. Continuing, but check branch state.")
100+
if out:
101+
print(out)
102+
if err:
103+
print(err)
104+
105+
def merge_source_into_target(source: str, target: str, dry_run: bool):
106+
print(f"Merging {source} -> {target}...")
107+
rc, out, err = run_git(["merge", "--no-edit", source], dry_run, capture_output=True)
108+
if dry_run:
109+
return True
110+
if rc == 0:
111+
print(out)
112+
return True
113+
# Merge failed. Check for conflicts
114+
print("Merge command returned non-zero. Checking for conflicts...")
115+
rc2, status_out, _ = run_git(["status", "--porcelain"])
116+
if any(line.startswith(("UU","AA","DU","UD","AU","UA","??")) for line in status_out.splitlines()):
117+
print("Merge appears to have conflicts. Attempting to abort the merge...", file=sys.stderr)
118+
rc3, abort_out, abort_err = run_git(["merge", "--abort"])
119+
if rc3 != 0:
120+
print("Failed to abort merge automatically. You must resolve the repository state manually.", file=sys.stderr)
121+
if abort_out:
122+
print(abort_out)
123+
if abort_err:
124+
print(abort_err)
125+
else:
126+
print("Merge aborted.")
127+
sys.exit(1)
128+
else:
129+
# Non-conflict failure (some other error)
130+
print("Merge failed for an unknown reason.", file=sys.stderr)
131+
if out:
132+
print(out)
133+
if err:
134+
print(err, file=sys.stderr)
135+
sys.exit(1)
136+
137+
def do_push(branch_name: str, dry_run: bool):
138+
print(f"Pushing branch {branch_name}")
139+
rc, out, err = run_git(["push"], dry_run)
140+
if rc != 0:
141+
print(f"Failed to push branch {branch_name}", file=sys.stderr)
142+
if out:
143+
print(out)
144+
if err:
145+
print(err)
146+
sys.exit(1)
147+
148+
def tag_and_push(branch: str, version: str, push: bool, dry_run: bool):
149+
tag = f"{branch}-{version}"
150+
# check tag does not already exist
151+
rc, _, _ = run_git(["rev-parse", "-q", "--verify", f"refs/tags/{tag}"])
152+
if rc == 0:
153+
print(f"Tag '{tag}' already exists. Aborting to avoid overwriting.", file=sys.stderr)
154+
sys.exit(1)
155+
print(f"Creating tag '{tag}'...")
156+
rc, out, err = run_git(["tag", tag], dry_run)
157+
if rc != 0:
158+
print(f"Failed to create tag {tag}.", file=sys.stderr)
159+
if out:
160+
print(out)
161+
if err:
162+
print(err)
163+
sys.exit(1)
164+
if push:
165+
print(f"Pushing tag '{tag}' to origin...")
166+
rc, out, err = run_git(["push", "origin", tag], dry_run)
167+
if rc != 0:
168+
print(f"Failed to push tag {tag} to origin.", file=sys.stderr)
169+
if out:
170+
print(out)
171+
if err:
172+
print(err)
173+
sys.exit(1)
174+
175+
def fetch_origin(dry_run: bool):
176+
print("Fetching origin ...")
177+
rc, out, err = run_git(["fetch", "origin"], dry_run)
178+
if rc != 0:
179+
print("Warning: 'git fetch origin' returned non-zero.", file=sys.stderr)
180+
if out:
181+
print(out)
182+
if err:
183+
print(err)
184+
185+
def parse_args():
186+
p = argparse.ArgumentParser(description="Merge release branches and create/push tags non-interactively.")
187+
p.add_argument("version", help="version string to append to tags (used as <branch>-<version>)")
188+
p.add_argument("--branches", nargs="+",
189+
default=BRANCHES,
190+
help="space-separated list of branches in order (default: %(default)s)")
191+
p.add_argument("--dry-run", action="store_true", help="show commands without executing them")
192+
p.add_argument("--no-push", dest="push", action="store_false", help="do not push tags to origin")
193+
return p.parse_args()
194+
195+
def main():
196+
args = parse_args()
197+
version = args.version
198+
branches = args.branches
199+
dry_run = args.dry_run
200+
push = args.push
201+
202+
if not sanity_check_file_versions(version):
203+
sys.exit(1)
204+
205+
if not working_tree_clean():
206+
print("Working tree is not clean. Please commit or stash changes before running this script.", file=sys.stderr)
207+
rc, status_out, _ = run_git(["status", "--porcelain"])
208+
if status_out:
209+
print(status_out)
210+
sys.exit(1)
211+
212+
fetch_origin(dry_run=dry_run)
213+
214+
prev = "dev"
215+
for br in branches:
216+
print("\n" + "="*60)
217+
print(f"Processing branch: {br} (merge {prev} -> {br})")
218+
print("="*60)
219+
220+
ensure_branch_local_or_origin(br, dry_run=dry_run)
221+
checkout_branch(br, dry_run=dry_run)
222+
pull_ff_only(br, dry_run=dry_run)
223+
224+
merge_ok = merge_source_into_target(prev, br, dry_run=dry_run)
225+
if not merge_ok:
226+
print(f"Merge of {prev} into {br} failed. Aborting.", file=sys.stderr)
227+
sys.exit(1)
228+
229+
if push:
230+
do_push(br, dry_run=dry_run)
231+
232+
tag_and_push(br, version, push=push, dry_run=dry_run)
233+
234+
prev = br
235+
236+
print("\nSwitching back to dev branch...")
237+
checkout_branch("dev", dry_run=dry_run)
238+
239+
print("\nAll done. Created tags for version", version, "on branches:", ", ".join(branches))
240+
241+
if __name__ == "__main__":
242+
main()

gradle.properties

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ org.gradle.jvmargs=-Xmx1g
2323

2424
ideaVersionName = 2025.3
2525

26-
coreVersion = 1.8.9
26+
coreVersion = 1.8.10
2727

2828
# Silences a build-time warning because we are bundling our own kotlin library
2929
kotlin.stdlib.default.dependency = false

readme.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ Minecraft Development for IntelliJ
3131
</tr>
3232
</table>
3333

34-
Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.8.9-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327)
34+
Info and Documentation [![Current Release](https://img.shields.io/badge/release-1.8.10-orange.svg?style=flat-square)](https://plugins.jetbrains.com/plugin/8327)
3535
----------------------
3636

3737
<a href="https://discord.gg/j6UNcfr"><img src="https://i.imgur.com/JXu9C1G.png" height="48px"></img></a>

src/main/kotlin/creator/JdkComboBoxWithPreference.kt

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
package com.demonwav.mcdev.creator
2222

23+
import com.demonwav.mcdev.util.invokeLater
2324
import com.intellij.ide.util.PropertiesComponent
2425
import com.intellij.ide.util.projectWizard.ProjectWizardUtil
2526
import com.intellij.ide.util.projectWizard.WizardContext
@@ -42,6 +43,7 @@ import com.intellij.openapi.util.Disposer
4243
import com.intellij.ui.dsl.builder.Cell
4344
import com.intellij.ui.dsl.builder.Row
4445
import javax.swing.JComponent
46+
import org.jetbrains.concurrency.runAsync
4547

4648
internal class JdkPreferenceData(
4749
var jdk: JavaSdkVersion,
@@ -89,15 +91,17 @@ class JdkComboBoxWithPreference internal constructor(
8991
preferenceData.jdk = version
9092
reloadModel()
9193

92-
for (jdkVersion in version.ordinal until JavaSdkVersion.values().size) {
93-
val jdk = JavaSdkVersion.values()[jdkVersion]
94+
for (jdkVersion in version.ordinal until JavaSdkVersion.entries.size) {
95+
val jdk = JavaSdkVersion.entries[jdkVersion]
9496

9597
val preferredSdkPath = preferenceData.sdkPathByJdk[jdk]
9698
if (preferredSdkPath != null) {
9799
val sdk = model.sdks.firstOrNull { it.homePath == preferredSdkPath }
98100
?: suggestions.firstOrNull { it.homePath == preferredSdkPath }
99101
if (sdk != null) {
100-
setSelectedItem(sdk)
102+
runAsync {
103+
setSelectedItem(sdk)
104+
}
101105
return
102106
}
103107
}
@@ -145,7 +149,7 @@ fun Row.jdkComboBoxWithPreference(
145149
for (preferenceDataStr in preferenceDataStrs) {
146150
val parts = preferenceDataStr.split('=', limit = 2)
147151
val featureVersion = parts.firstOrNull()?.toIntOrNull() ?: continue
148-
val knownJdkVersions = JavaSdkVersion.values()
152+
val knownJdkVersions = JavaSdkVersion.entries
149153
if (featureVersion !in knownJdkVersions.indices) {
150154
continue
151155
}
@@ -176,7 +180,9 @@ fun Row.jdkComboBoxWithPreference(
176180
}
177181

178182
val lastUsedSdk = stateComponent.getValue(selectedJdkProperty)
179-
ProjectWizardUtil.preselectJdkForNewModule(project, lastUsedSdk, comboBox) { true }
183+
runAsync {
184+
ProjectWizardUtil.preselectJdkForNewModule(project, lastUsedSdk, comboBox) { true }
185+
}
180186

181187
val windowChild = context.getUserData(AbstractWizard.KEY)!!.contentPanel
182188
comboBox.loadSuggestions(windowChild, context.disposable)

src/main/kotlin/creator/custom/CreatorTemplateProcessor.kt

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import com.intellij.codeInsight.actions.ReformatCodeProcessor
3434
import com.intellij.ide.projectView.ProjectView
3535
import com.intellij.ide.util.projectWizard.WizardContext
3636
import com.intellij.openapi.application.WriteAction
37+
import com.intellij.openapi.concurrency.awaitPromise
3738
import com.intellij.openapi.diagnostic.Attachment
3839
import com.intellij.openapi.diagnostic.ControlFlowException
3940
import com.intellij.openapi.diagnostic.thisLogger
@@ -53,11 +54,15 @@ import com.intellij.ui.dsl.builder.Panel
5354
import com.intellij.ui.dsl.builder.panel
5455
import com.intellij.util.application
5556
import java.nio.file.Path
57+
import java.time.Duration
58+
import java.util.concurrent.TimeUnit
5659
import java.util.function.Consumer
5760
import kotlin.io.path.createDirectories
5861
import kotlin.io.path.writeText
5962
import kotlinx.coroutines.CoroutineScope
6063
import kotlinx.coroutines.launch
64+
import org.jetbrains.concurrency.await
65+
import org.jetbrains.concurrency.runAsync
6166

6267
interface ExternalTemplatePropertyProvider {
6368

@@ -268,7 +273,11 @@ class CreatorTemplateProcessor(
268273
destPath.parent.createDirectories()
269274
destPath.writeText(processedContent)
270275

271-
val virtualFile = destPath.refreshAndFindVirtualFile()
276+
val virtualFile = runCatching {
277+
runAsync {
278+
destPath.refreshAndFindVirtualFile()
279+
}.blockingGet(20, TimeUnit.MILLISECONDS)
280+
}.getOrNull()
272281
if (virtualFile != null) {
273282
generatedFiles.add(file to virtualFile)
274283
} else {

0 commit comments

Comments
 (0)