diff --git a/src/server/install.ts b/src/server/install.ts index 8ee3f64..70fd570 100644 --- a/src/server/install.ts +++ b/src/server/install.ts @@ -106,6 +106,9 @@ export class BazelBSPInstaller { this.outputChannel.show() return false } + + // Temporary: Patch the python_info file to be compatible with rules_py. + await this.patchPythonAspect(root) return true } @@ -235,4 +238,43 @@ export class BazelBSPInstaller { bazelBinaryPath: bazelBinaryPath, } } + + /** + * Temporary solution to ensure that the rules_python load statement is always included in the Python aspect. + * This is needed for compatibility with targets that no longer include the builtin Python providers (e.g. rules_py). + * This will be addressed by https://github.com/JetBrains/hirschgarten/pull/210 once we have a standalone version of the server back in place. + * @param root + */ + private async patchPythonAspect(root: string) { + // Get the current contents of the Python aspect template, as added by the installer. + const targetFile = path.join( + root, + '.bazelbsp/aspects/rules/python/python_info.bzl.template' + ) + + let content = '' + try { + content = await fs.readFile(targetFile, 'utf8') + } catch { + this.outputChannel.appendLine( + `Failed to read file ${targetFile}. Skipping patch.` + ) + } + + // Make rules_python load statement non-conditional for compatibility with rules_py. + const regex = + /#if\( \$pythonEnabled == "true" && \$bazel8OrAbove == "true" \)[\s\S]*?#end/ + const replacement = + 'load("@rules_python//python:defs.bzl", "PyInfo", "PyRuntimeInfo")' + + // Replace the matched block with the replacement. + content = content.replace(regex, replacement) + try { + await fs.writeFile(targetFile, content, 'utf8') + } catch (err) { + this.outputChannel.appendLine( + `Failed to write updated Python aspect to ${targetFile}. Skipping patch.` + ) + } + } } diff --git a/src/test/suite/install.test.ts b/src/test/suite/install.test.ts index 4c7df70..eeaf007 100644 --- a/src/test/suite/install.test.ts +++ b/src/test/suite/install.test.ts @@ -72,6 +72,14 @@ suite('BSP Installer', () => { .withArgs(settings.SettingName.SERVER_INSTALL_MODE) .returns('Prompt') + sandbox.stub(fs, 'readFile').resolves( + `#if( $pythonEnabled == "true" && $bazel8OrAbove == "true" ) +load("@rules_python//python:defs.bzl", "PyInfo", "PyRuntimeInfo") +#end + +load("//aspects:utils/utils.bzl", "create_struct", "file_location", "to_file_location")` + ) + // Simulated data returned by coursier download request. const sampleData = 'sample data' sandbox.stub(axios.default, 'get').resolves({data: sampleData} as any) @@ -89,6 +97,12 @@ suite('BSP Installer', () => { assert.ok(spawnStub.getCalls()[0].args[0].includes(coursierPath)) assert.ok(spawnStub.getCalls()[0].args[0].includes('--jvm openjdk:1.17.0')) assert.ok(installResult) + + const updatedContents = writeFileSpy.getCalls()[1].args[1] + const expectedContents = `load("@rules_python//python:defs.bzl", "PyInfo", "PyRuntimeInfo") + +load("//aspects:utils/utils.bzl", "create_struct", "file_location", "to_file_location")` + assert.equal(updatedContents, expectedContents) }) test('failed coursier download', async () => {