Skip to content

Commit 9a4d196

Browse files
committed
Add bala extraction in PullCommand
1 parent 1600514 commit 9a4d196

File tree

6 files changed

+50
-9
lines changed

6 files changed

+50
-9
lines changed

cli/ballerina-cli/src/main/java/io/ballerina/cli/cmd/PullCommand.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,8 @@ public void execute() {
150150
}
151151

152152
Path packagePathInBalaCache = ProjectUtils.createAndGetHomeReposPath()
153-
.resolve(ProjectConstants.BALA_DIR_NAME).resolve(orgName).resolve(packageName);
153+
.resolve(ProjectConstants.REPOSITORIES_DIR).resolve(ProjectConstants.CENTRAL_REPOSITORY_CACHE_NAME)
154+
.resolve(orgName).resolve(packageName);
154155
// create directory path in bala cache
155156
try {
156157
createDirectories(packagePathInBalaCache);

cli/central-client/build.gradle

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ dependencies {
3535
implementation 'com.google.code.gson:gson'
3636
implementation 'com.google.code.findbugs:jsr305'
3737
implementation 'com.github.zafarkhaja:java-semver'
38+
implementation 'commons-io:commons-io'
3839
testCompile 'org.testng:testng'
3940
testCompile 'org.awaitility:awaitility'
4041
testImplementation 'org.powermock:powermock-mockito-release-full'

cli/central-client/src/main/java/module-info.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,5 @@
99
requires jdk.httpserver;
1010
requires io.ballerina.runtime;
1111
requires java.semver;
12+
requires org.apache.commons.io;
1213
}

cli/central-client/src/main/java/org/ballerinalang/central/client/CentralAPIClient.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -331,7 +331,7 @@ public void pullPackage(String org, String name, String version, Path packagePat
331331
conn.setRequestProperty(CONTENT_DISPOSITION, contentDisposition);
332332

333333
boolean isNightlyBuild = ballerinaVersion.contains("SNAPSHOT");
334-
createBalaInHomeRepo(conn, packagePathInBalaCache, org + "/" + name, isNightlyBuild, newUrl,
334+
createBalaInHomeRepo(conn, packagePathInBalaCache, org, name, isNightlyBuild, newUrl,
335335
contentDisposition, outStream, logFormatter);
336336
} else {
337337
try (BufferedReader reader = new BufferedReader(

cli/central-client/src/main/java/org/ballerinalang/central/client/Utils.java

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import com.google.gson.reflect.TypeToken;
2626
import me.tongfei.progressbar.ProgressBar;
2727
import me.tongfei.progressbar.ProgressBarStyle;
28+
import org.apache.commons.io.FileUtils;
2829
import org.ballerinalang.central.client.exceptions.CentralClientException;
2930
import org.ballerinalang.central.client.exceptions.ConnectionErrorException;
3031
import org.ballerinalang.central.client.exceptions.PackageAlreadyExistsException;
@@ -36,13 +37,20 @@
3637
import java.net.HttpURLConnection;
3738
import java.net.MalformedURLException;
3839
import java.net.ProtocolException;
40+
import java.net.URI;
3941
import java.net.URL;
42+
import java.nio.file.FileSystem;
43+
import java.nio.file.FileSystems;
4044
import java.nio.file.Files;
4145
import java.nio.file.Path;
4246
import java.nio.file.Paths;
47+
import java.nio.file.StandardCopyOption;
4348
import java.security.KeyManagementException;
4449
import java.security.NoSuchAlgorithmException;
50+
import java.util.HashMap;
4551
import java.util.List;
52+
import java.util.Optional;
53+
import java.util.stream.Collectors;
4654

4755
import javax.net.ssl.HttpsURLConnection;
4856
import javax.net.ssl.SSLContext;
@@ -86,14 +94,15 @@ public void checkServerTrusted(java.security.cert.X509Certificate[] certs, Strin
8694
*
8795
* @param conn http connection
8896
* @param pkgPathInBalaCache package path in bala cache, <user.home>.ballerina/bala_cache/<org-name>/<pkg-name>
89-
* @param pkgNameWithOrg package name with org, <org-name>/<pkg-name>
97+
* @param pkgOrg package org
98+
* @param pkgName package name
9099
* @param isNightlyBuild is nightly build
91100
* @param newUrl new redirect url
92101
* @param contentDisposition content disposition header
93102
* @param outStream Output print stream
94103
* @param logFormatter log formatter
95104
*/
96-
public static void createBalaInHomeRepo(HttpURLConnection conn, Path pkgPathInBalaCache, String pkgNameWithOrg,
105+
public static void createBalaInHomeRepo(HttpURLConnection conn, Path pkgPathInBalaCache, String pkgOrg, String pkgName,
97106
boolean isNightlyBuild, String newUrl, String contentDisposition, PrintStream outStream,
98107
LogFormatter logFormatter) throws CentralClientException {
99108
long responseContentLength = conn.getContentLengthLong();
@@ -110,17 +119,22 @@ public static void createBalaInHomeRepo(HttpURLConnection conn, Path pkgPathInBa
110119

111120
String validPkgVersion = validatePackageVersion(pkgVersion, logFormatter);
112121
String balaFile = getBalaFileName(contentDisposition, uriParts[uriParts.length - 1]);
113-
Path balaCacheWithPkgPath = pkgPathInBalaCache.resolve(validPkgVersion);
122+
String platform = getPlatformFromBala(balaFile, pkgName, validPkgVersion);
123+
Path balaCacheWithPkgPath = pkgPathInBalaCache.resolve(validPkgVersion).resolve(platform);
114124
//<user.home>.ballerina/bala_cache/<org-name>/<pkg-name>/<pkg-version>
115125

116-
Path balaPath = Paths.get(balaCacheWithPkgPath.toString(), balaFile);
117-
if (balaPath.toFile().exists()) {
126+
try {
127+
if (Files.isDirectory(balaCacheWithPkgPath) && Files.list(balaCacheWithPkgPath).findAny().isPresent()) {
128+
throw new PackageAlreadyExistsException(
129+
logFormatter.formatLog("package already exists in the home repository: " + balaCacheWithPkgPath.toString()));
130+
}
131+
} catch (IOException e) {
118132
throw new PackageAlreadyExistsException(
119-
logFormatter.formatLog("package already exists in the home repository: " + balaPath.toString()));
133+
logFormatter.formatLog("error accessing bala : " + balaCacheWithPkgPath.toString()));
120134
}
121135

122136
createBalaFileDirectory(balaCacheWithPkgPath, logFormatter);
123-
writeBalaFile(conn, balaPath, pkgNameWithOrg + ":" + validPkgVersion, responseContentLength, outStream,
137+
writeBalaFile(conn, balaCacheWithPkgPath.resolve(balaFile), pkgOrg + "/" + pkgName + ":" + validPkgVersion, responseContentLength, outStream,
124138
logFormatter);
125139
handleNightlyBuild(isNightlyBuild, balaCacheWithPkgPath, logFormatter);
126140
}
@@ -194,6 +208,8 @@ static void writeBalaFile(HttpURLConnection conn, Path balaPath, String fullPkgN
194208
FileOutputStream outputStream = new FileOutputStream(balaPath.toString())) {
195209
writeAndHandleProgress(inputStream, outputStream, resContentLength / 1024, fullPkgName, outStream,
196210
logFormatter);
211+
extractBala(balaPath, Optional.of(balaPath.getParent()).get());
212+
Files.delete(balaPath);
197213
} catch (IOException e) {
198214
throw new CentralClientException(
199215
logFormatter.formatLog("error occurred copying the bala file: " + e.getMessage()));
@@ -343,4 +359,25 @@ static long getTotalFileSizeInKB(Path filePath) throws CentralClientException {
343359
static List<String> getAsList(String arrayString) {
344360
return new Gson().fromJson(arrayString, new TypeToken<List<String>>() { }.getType());
345361
}
362+
363+
private static String getPlatformFromBala(String balaName, String packageName, String version) {
364+
return balaName.split(packageName + "-")[1].split("-" + version)[0];
365+
}
366+
367+
private static void extractBala(Path balaFilePath, Path balaFileDestPath) throws IOException {
368+
Files.createDirectories(balaFileDestPath);
369+
URI zipURI = URI.create("jar:" + balaFilePath.toUri().toString());
370+
try (FileSystem zipFileSystem = FileSystems.newFileSystem(zipURI, new HashMap<>())) {
371+
Path packageRoot = zipFileSystem.getPath("/");
372+
List<Path> paths = Files.walk(packageRoot).filter(path -> path != packageRoot).collect(Collectors.toList());
373+
for (Path path : paths) {
374+
Path destPath = balaFileDestPath.resolve(packageRoot.relativize(path).toString());
375+
// Handle overwriting existing bala
376+
if (destPath.toFile().isDirectory()) {
377+
FileUtils.deleteDirectory(destPath.toFile());
378+
}
379+
Files.copy(path, destPath, StandardCopyOption.REPLACE_EXISTING);
380+
}
381+
}
382+
}
346383
}

compiler/ballerina-lang/src/main/java/io/ballerina/projects/util/ProjectConstants.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,5 @@ public class ProjectConstants {
107107
public static final String REPOSITORIES_DIR = "repositories";
108108
public static final String CENTRAL_REPOSITORY_NAME = "central.ballerina.io";
109109
public static final String LOCAL_REPOSITORY_NAME = "local";
110+
public static final String CENTRAL_REPOSITORY_CACHE_NAME = "central.ballerina.io";
110111
}

0 commit comments

Comments
 (0)