Skip to content

Commit

Permalink
Merge pull request ballerina-platform#43497 from azinneera/prj_api_re…
Browse files Browse the repository at this point in the history
…adme_new

Support custom md files for package documentation
  • Loading branch information
azinneera authored Nov 18, 2024
2 parents b6244de + fb27ea2 commit b517ec9
Show file tree
Hide file tree
Showing 147 changed files with 1,759 additions and 699 deletions.
105 changes: 76 additions & 29 deletions cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/CommandUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
import io.ballerina.projects.Settings;
import io.ballerina.projects.bala.BalaProject;
import io.ballerina.projects.internal.bala.BalToolJson;
import io.ballerina.projects.internal.bala.BalaJson;
import io.ballerina.projects.internal.bala.DependencyGraphJson;
import io.ballerina.projects.internal.bala.ModuleDependency;
import io.ballerina.projects.internal.bala.PackageJson;
Expand Down Expand Up @@ -81,6 +82,7 @@
import java.util.stream.Stream;

import static io.ballerina.cli.launcher.LauncherUtils.createLauncherException;
import static io.ballerina.projects.util.ProjectConstants.BALA_JSON;
import static io.ballerina.projects.util.ProjectConstants.BAL_TOOL_JSON;
import static io.ballerina.projects.util.ProjectConstants.BAL_TOOL_TOML;
import static io.ballerina.projects.util.ProjectConstants.DEPENDENCIES_TOML;
Expand Down Expand Up @@ -210,8 +212,10 @@ private static void addModules(Path balaPath, Path projectPath, String packageNa
Gson gson = new Gson();
Path packageJsonPath = balaPath.resolve(PACKAGE_JSON);
Path dependencyGraphJsonPath = balaPath.resolve(DEPENDENCY_GRAPH_JSON);
Path balToolJsonPath = balaPath.resolve(TOOL_DIR).resolve(ProjectConstants.BAL_TOOL_JSON);
Path balToolJsonPath = balaPath.resolve(TOOL_DIR).resolve(BAL_TOOL_JSON);
PackageJson templatePackageJson = null;
BalaJson templateBalaJson = null;
Path balaJsonPath = balaPath.resolve(BALA_JSON);
DependencyGraphJson templateDependencyGraphJson = null;
BalToolJson templateBalToolJson = null;

Expand All @@ -226,6 +230,17 @@ private static void addModules(Path balaPath, Path projectPath, String packageNa
getRuntime().exit(1);
}

try (InputStream inputStream = new FileInputStream(String.valueOf(balaJsonPath))) {
Reader fileReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
templateBalaJson = gson.fromJson(fileReader, BalaJson.class);
} catch (IOException e) {
printError(errStream,
"Error while reading the bala.json file: " + e.getMessage(),
null,
false);
getRuntime().exit(1);
}

if (dependencyGraphJsonPath.toFile().exists()) {
try (InputStream inputStream = new FileInputStream(String.valueOf(dependencyGraphJsonPath))) {
Reader fileReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
Expand Down Expand Up @@ -261,7 +276,7 @@ private static void addModules(Path balaPath, Path projectPath, String packageNa
Path ballerinaToml = projectPath.resolve(ProjectConstants.BALLERINA_TOML);
Files.createDirectories(projectPath);
Files.createFile(ballerinaToml);
writeBallerinaToml(ballerinaToml, templatePackageJson, packageName, platform);
writeBallerinaToml(ballerinaToml, templatePackageJson, templateBalaJson, packageName, platform);

if (dependencyGraphJsonPath.toFile().exists()) {
// Create Dependencies.toml
Expand All @@ -278,12 +293,15 @@ private static void addModules(Path balaPath, Path projectPath, String packageNa
copyToolDependencies(projectPath, balaPath.resolve(TOOL_DIR).resolve(LIBS_DIR));
}

// Create Package.md
Path packageMDFilePath = balaPath.resolve("docs")
.resolve(ProjectConstants.PACKAGE_MD_FILE_NAME);
Path toPackageMdPath = projectPath.resolve(ProjectConstants.PACKAGE_MD_FILE_NAME);
if (Files.exists(packageMDFilePath)) {
Files.copy(packageMDFilePath, toPackageMdPath, StandardCopyOption.REPLACE_EXISTING);
// Create README.md
Path toPackageMdPath = projectPath.resolve(ProjectConstants.README_MD_FILE_NAME);
Path docFilePath = balaPath.resolve("docs").resolve(ProjectConstants.PACKAGE_MD_FILE_NAME);
if (templatePackageJson.getReadme() != null) {
// New bala structure
docFilePath = balaPath.resolve(templatePackageJson.getReadme());
}
if (Files.exists(docFilePath)) {
Files.copy(docFilePath, toPackageMdPath, StandardCopyOption.REPLACE_EXISTING);
}

// Create default .gitignore
Expand All @@ -299,6 +317,16 @@ private static void addModules(Path balaPath, Path projectPath, String packageNa
try (Stream<Path> pathStream = Files.list(modulesRoot)) {
modulesList = pathStream.toList();
}
copyIcon(balaPath, projectPath);
copyPlatformLibraries(balaPath, projectPath);
copyIncludeFiles(balaPath, projectPath, templatePackageJson);

Map<String, String> otherModulesMap = new HashMap<>();
if (templatePackageJson.getModules() != null) {
otherModulesMap = templatePackageJson.getModules().stream().collect(
Collectors.toMap(PackageManifest.Module::name, PackageManifest.Module::readme));
}

for (Path moduleRoot : modulesList) {
Path moduleDir = Optional.of(moduleRoot.getFileName()).get();
Path destDir;
Expand All @@ -311,17 +339,20 @@ private static void addModules(Path balaPath, Path projectPath, String packageNa
}
Files.walkFileTree(moduleRoot, new FileUtils.Copy(moduleRoot, destDir, templatePkgName, packageName));

// Copy Module.md
// Copy README.md
Path moduleMdSource = moduleMdDirRoot.resolve(moduleDir).resolve(ProjectConstants.MODULE_MD_FILE_NAME);

if (templatePackageJson.getReadme() != null) {
String moduleName = Optional.of(moduleRoot.getFileName()).get().toString();
if (otherModulesMap.containsKey(moduleName)) {
moduleMdSource = balaPath.resolve(otherModulesMap.get(moduleName));
}
}
if (Files.exists(moduleMdSource)) {
Files.copy(moduleMdSource, destDir.resolve(ProjectConstants.MODULE_MD_FILE_NAME),
Files.copy(moduleMdSource, destDir.resolve(ProjectConstants.README_MD_FILE_NAME),
StandardCopyOption.REPLACE_EXISTING);
}
}

copyIcon(balaPath, projectPath);
copyPlatformLibraries(balaPath, projectPath);
copyIncludeFiles(balaPath, projectPath, templatePackageJson);
}

private static void copyIcon(Path balaPath, Path projectPath) {
Expand Down Expand Up @@ -468,7 +499,7 @@ private static void pullPackageFromRemote(String orgName, String packageName, St
RepoUtils.getBallerinaVersion(), false);
}

public static void writeBallerinaToml(Path balTomlPath, PackageJson packageJson,
public static void writeBallerinaToml(Path balTomlPath, PackageJson packageJson, BalaJson balaJson,
String packageName, String platform)
throws IOException {

Expand All @@ -478,16 +509,6 @@ public static void writeBallerinaToml(Path balTomlPath, PackageJson packageJson,
Files.writeString(balTomlPath, "\nname = \"" + packageName + "\"", StandardOpenOption.APPEND);
Files.writeString(balTomlPath, "\nversion = \"" + packageJson.getVersion() + "\"",
StandardOpenOption.APPEND);
List<String> newModuleNames = packageJson.getExport().stream().map(module ->
module.replaceFirst(packageJson.getName(), packageName)).toList();

StringJoiner stringJoiner = new StringJoiner(",");
for (String newModuleName : newModuleNames) {
stringJoiner.add("\"" + newModuleName + "\"");
}

Files.writeString(balTomlPath, "\nexport = [" + stringJoiner + "]"
.replaceFirst(packageJson.getName(), packageName), StandardOpenOption.APPEND);
Files.writeString(balTomlPath, "\ndistribution = \"" + packageJson.getBallerinaVersion()
+ "\"", StandardOpenOption.APPEND);

Expand All @@ -501,6 +522,31 @@ public static void writeBallerinaToml(Path balTomlPath, PackageJson packageJson,
Files.writeString(balTomlPath, "\n\n[build-options]", StandardOpenOption.APPEND);
Files.writeString(balTomlPath, "\nobservabilityIncluded = true\n", StandardOpenOption.APPEND);

StringJoiner stringJoiner = new StringJoiner("\n");
if ("2.0.0".equals(balaJson.getBala_version())) {
List<String> newModuleNames = packageJson.getExport().stream().map(module ->
module.replaceFirst(packageJson.getName(), packageName)).toList();

for (String newModuleName : newModuleNames) {
if (newModuleName.equals(packageName)) {
continue;
}
stringJoiner.add("\n[[package.modules]]");
stringJoiner.add("name = \"" + newModuleName.replaceFirst(packageJson.getName(), packageName) + "\"");
stringJoiner.add("export = true");
}
} else {
for (PackageManifest.Module module : packageJson.getModules()) {
stringJoiner.add("\n[[package.modules]]");
stringJoiner.add("name = \"" + module.name().replaceFirst(packageJson.getName(), packageName) + "\"");
stringJoiner.add("export = true");
}
}

if (!stringJoiner.toString().isEmpty()) {
Files.writeString(balTomlPath, stringJoiner + "\n", StandardOpenOption.APPEND);
}

JsonArray platformLibraries = packageJson.getPlatformDependencies();
if (platformLibraries == null) {
return;
Expand Down Expand Up @@ -967,9 +1013,10 @@ private static void initLibPackage(Path path, String packageName) throws IOExcep

Files.writeString(ballerinaToml, defaultManifest);

// Create Package.md
String packageMd = FileUtils.readFileAsString(NEW_CMD_DEFAULTS + "/Package.md");
write(path.resolve(ProjectConstants.PACKAGE_MD_FILE_NAME), packageMd.getBytes(StandardCharsets.UTF_8));
// Create README.md
String packageMd = FileUtils.readFileAsString(NEW_CMD_DEFAULTS + "/" +
ProjectConstants.README_MD_FILE_NAME);
write(path.resolve(ProjectConstants.README_MD_FILE_NAME), packageMd.getBytes(StandardCharsets.UTF_8));
}

/**
Expand All @@ -990,7 +1037,7 @@ private static void initToolPackage(Path path, String packageName) throws IOExce
.replace(DIST_VERSION, RepoUtils.getBallerinaShortVersion());
Files.writeString(ballerinaToml, defaultManifest);

Path balToolToml = path.resolve(ProjectConstants.BAL_TOOL_TOML);
Path balToolToml = path.resolve(BAL_TOOL_TOML);
Files.createFile(balToolToml);

String balToolManifest = FileUtils.readFileAsString(NEW_CMD_DEFAULTS + "/" + "manifest-tool.toml");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,20 @@
import io.ballerina.projects.Project;
import io.ballerina.projects.ProjectException;
import io.ballerina.projects.directory.BuildProject;
import io.ballerina.projects.internal.ProjectDiagnosticErrorCode;
import io.ballerina.projects.util.ProjectConstants;
import io.ballerina.projects.util.ProjectUtils;
import io.ballerina.toml.semantic.TomlType;
import io.ballerina.toml.semantic.ast.TomlTableNode;
import io.ballerina.tools.diagnostics.Diagnostic;
import org.wso2.ballerinalang.util.RepoUtils;
import picocli.CommandLine;

import java.io.PrintStream;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static io.ballerina.cli.cmd.Constants.PACK_COMMAND;
import static io.ballerina.projects.internal.ManifestBuilder.getStringValueFromTomlTableNode;
Expand Down Expand Up @@ -249,6 +253,12 @@ public void execute() {
// Check package files are modified after last build
boolean isPackageModified = isProjectUpdated(project);

Optional<Diagnostic> deprecatedDocWarning = ProjectUtils.getProjectLoadingDiagnostic().stream().filter(
diagnostic -> diagnostic.diagnosticInfo().code().equals(
ProjectDiagnosticErrorCode.DEPRECATED_DOC_FILE.diagnosticId())).findAny();

deprecatedDocWarning.ifPresent(this.errStream::println);

TaskExecutor taskExecutor = new TaskExecutor.TaskBuilder()
.addTask(new CleanTargetDirTask(isPackageModified, buildOptions.enableCache()), isSingleFileBuild)
.addTask(new RunBuildToolsTask(outStream), isSingleFileBuild)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ public void execute() {
if (!FileUtils.getExtension(balaPath).equals("bala")) {
throw new ProjectException("file provided is not a bala file: " + balaPath + ".");
}
validatePackageMdAndBalToml(balaPath);
validateReadmeAndBalToml(balaPath);
pushBalaToCustomRepo(balaPath);
return;
}
Expand All @@ -216,7 +216,7 @@ public void execute() {
if (!FileUtils.getExtension(balaPath).equals("bala")) {
throw new ProjectException("file provided is not a bala file: " + balaPath + ".");
}
validatePackageMdAndBalToml(balaPath);
validateReadmeAndBalToml(balaPath);
pushBalaToCustomRepo(balaPath, mvnClient);
}

Expand All @@ -243,7 +243,7 @@ public void execute() {
if (!FileUtils.getExtension(balaPath).equals("bala")) {
throw new ProjectException("file provided is not a bala file: " + balaPath + ".");
}
validatePackageMdAndBalToml(balaPath);
validateReadmeAndBalToml(balaPath);
pushBalaToRemote(balaPath, client);
}
}
Expand Down Expand Up @@ -349,28 +349,37 @@ private static Path validateBalaFile(BuildProject project, Path customBalaPath)
+ "' in " + ProjectConstants.BALLERINA_TOML
+ " file. Run 'bal pack' to recompile and generate the bala.");
}
validatePackageMdAndBalToml(packageBalaFile);
validateReadmeAndBalToml(packageBalaFile);

// bala file path
return packageBalaFile;
}

private static void validatePackageMdAndBalToml(Path balaPath) {
private static void validateReadmeAndBalToml(Path balaPath) {
ProjectEnvironmentBuilder defaultBuilder = ProjectEnvironmentBuilder.getDefaultBuilder();
defaultBuilder.addCompilationCacheFactory(TempDirCompilationCache::from);
BalaProject balaProject = BalaProject.loadProject(defaultBuilder, balaPath);

try (ZipInputStream zip = new ZipInputStream(Files.newInputStream(balaPath, StandardOpenOption.READ))) {
ZipEntry entry;
String readme;
while ((entry = zip.getNextEntry()) != null) {
if (entry.getName().equals(
ProjectConstants.BALA_DOCS_DIR + "/" + ProjectConstants.PACKAGE_MD_FILE_NAME)) {
if (balaProject.currentPackage().manifest().readme() == null) {
readme = ProjectConstants.BALA_DOCS_DIR + "/" + ProjectConstants.PACKAGE_MD_FILE_NAME;
} else {
readme = balaProject.currentPackage().manifest().readme();
}
if (entry.getName().equals(readme)) {
if (entry.getSize() == 0) {
throw new ProjectException(ProjectConstants.PACKAGE_MD_FILE_NAME + " cannot be empty.");
throw new ProjectException("README file cannot be empty.");
}
return;
}
}
} catch (IOException e) {
throw new ProjectException("error while validating the bala file: " + e.getMessage(), e);
}
throw new ProjectException(ProjectConstants.PACKAGE_MD_FILE_NAME + " is missing in bala file:" + balaPath);
throw new ProjectException("README file is missing in the bala file:" + balaPath);
}

private void pushBalaToCustomRepo(Path balaFilePath) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;

import static io.ballerina.cli.launcher.LauncherUtils.createLauncherException;
Expand Down Expand Up @@ -220,10 +221,11 @@ public void execute(Project project) {
start = System.currentTimeMillis();
}

String projectLoadingDiagnostic = ProjectUtils.getProjectLoadingDiagnostic();
if (projectLoadingDiagnostic != null && !projectLoadingDiagnostic.isEmpty()) {
out.println(projectLoadingDiagnostic);
}
Optional<Diagnostic> projectLoadingDiagnostic = ProjectUtils.getProjectLoadingDiagnostic().stream().filter(
diagnostic -> diagnostic.diagnosticInfo().code().equals(
ProjectDiagnosticErrorCode.DEPRECATED_RESOURCES_STRUCTURE.diagnosticId())).findAny();

projectLoadingDiagnostic.ifPresent(out::println);
PackageCompilation packageCompilation = project.currentPackage().getCompilation();
if (project.buildOptions().dumpBuildTime()) {
BuildTime.getInstance().packageCompilationDuration = System.currentTimeMillis() - start;
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package io.ballerina.cli.cmd;

import com.google.gson.Gson;
import io.ballerina.projects.internal.bala.BalaJson;
import io.ballerina.projects.internal.bala.DependencyGraphJson;
import io.ballerina.projects.internal.bala.PackageJson;
import org.testng.Assert;
Expand Down Expand Up @@ -58,12 +59,18 @@ public void testWriteBallerinaToml() throws IOException {
Reader fileReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
packageJson = new Gson().fromJson(fileReader, PackageJson.class);
}
BalaJson balaJson;
try (InputStream inputStream = new FileInputStream(
String.valueOf(COMMAND_UTIL_RESOURCE_DIR.resolve("sample-bala.json")))) {
Reader fileReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
balaJson = new Gson().fromJson(fileReader, BalaJson.class);
}

// Create empty Ballerina.toml
Path ballerinaTomlPath = Files.createFile(COMMAND_UTIL_RESOURCE_DIR.resolve(BALLERINA_TOML));

// Test writeBallerinaToml method
writeBallerinaToml(ballerinaTomlPath, packageJson, "gsheet_new_row_to_github_new_issue", "any");
writeBallerinaToml(ballerinaTomlPath, packageJson, balaJson, "gsheet_new_row_to_github_new_issue", "any");
Assert.assertEquals(readFileAsString(COMMAND_UTIL_RESOURCE_DIR.resolve(BALLERINA_TOML)),
readFileAsString(COMMAND_UTIL_RESOURCE_DIR.resolve("expected-ballerina.toml")));
}
Expand Down
Loading

0 comments on commit b517ec9

Please sign in to comment.