Skip to content

Commit d5241fb

Browse files
committed
Create issue package via the --create-issue-package option for convenient issue reporting. Currently we consider classPath, appClassPath, inputClasses, and outputDir.
1 parent e7489dc commit d5241fb

File tree

3 files changed

+107
-0
lines changed

3 files changed

+107
-0
lines changed

src/main/java/pascal/taie/Main.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import pascal.taie.config.PlanConfig;
3636
import pascal.taie.config.Scope;
3737
import pascal.taie.frontend.cache.CachedWorldBuilder;
38+
import pascal.taie.util.IssuePackager;
3839
import pascal.taie.util.RuntimeInfoLogger;
3940
import pascal.taie.util.Timer;
4041
import pascal.taie.util.collection.Lists;
@@ -60,6 +61,9 @@ public static void main(String... args) {
6061
}
6162
buildWorld(options, plan.analyses());
6263
executePlan(plan);
64+
if (options.isCreateIssuePackage()) {
65+
IssuePackager.createIssuePackage(options);
66+
}
6367
}, "Tai-e");
6468
LoggerConfigs.reconfigure();
6569
}

src/main/java/pascal/taie/config/Options.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ public void printHelp() {
9494
cmd.usage(System.out);
9595
}
9696

97+
@JsonProperty
98+
@Option(names = "--create-issue-package",
99+
description = "Create reproducible package for issue reporting",
100+
defaultValue = "false")
101+
private boolean createIssuePackage;
102+
103+
public boolean isCreateIssuePackage() {
104+
return createIssuePackage;
105+
}
106+
97107
// ---------- program options ----------
98108
@JsonProperty
99109
@JsonSerialize(contentUsing = FilePathSerializer.class)
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/*
2+
* Tai-e: A Static Analysis Framework for Java
3+
*
4+
* Copyright (C) 2022 Tian Tan <tiantan@nju.edu.cn>
5+
* Copyright (C) 2022 Yue Li <yueli@nju.edu.cn>
6+
*
7+
* This file is part of Tai-e.
8+
*
9+
* Tai-e is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License
11+
* as published by the Free Software Foundation, either version 3
12+
* of the License, or (at your option) any later version.
13+
*
14+
* Tai-e is distributed in the hope that it will be useful,but WITHOUT
15+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
16+
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
17+
* Public License for more details.
18+
*
19+
* You should have received a copy of the GNU Lesser General Public
20+
* License along with Tai-e. If not, see <https://www.gnu.org/licenses/>.
21+
*/
22+
23+
package pascal.taie.util;
24+
25+
import pascal.taie.config.Options;
26+
27+
import java.io.File;
28+
import java.io.FileInputStream;
29+
import java.io.FileOutputStream;
30+
import java.io.IOException;
31+
import java.util.ArrayList;
32+
import java.util.List;
33+
import java.util.Objects;
34+
import java.util.zip.ZipEntry;
35+
import java.util.zip.ZipOutputStream;
36+
37+
public class IssuePackager {
38+
public static void createIssuePackage(Options options) {
39+
try {
40+
List<Source> filePaths = new ArrayList<>();
41+
filePaths.add(new Source("output", new File(options.getOutputDir().getCanonicalPath())));
42+
options.getClassPath().stream()
43+
.map(path -> new Source("cp", new File(path)))
44+
.forEach(filePaths::add);
45+
options.getAppClassPath().stream()
46+
.map(path -> new Source("acp", new File(path)))
47+
.forEach(filePaths::add);
48+
options.getInputClasses().stream()
49+
.map(path -> new Source("input-classes", new File(path)))
50+
.forEach(filePaths::add);
51+
createZipFile("package.zip", filePaths);
52+
} catch (IOException e) {
53+
throw new RuntimeException(e);
54+
}
55+
}
56+
57+
private static void createZipFile(String zipFileName, List<Source> filePaths) {
58+
try (ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(zipFileName))) {
59+
for (Source source : filePaths) {
60+
File file = source.file;
61+
String category = source.category;
62+
addToZipFile(category, file, zos);
63+
}
64+
} catch (IOException e) {
65+
throw new RuntimeException(e);
66+
}
67+
}
68+
69+
private static void addToZipFile(String category, File file, ZipOutputStream zos) {
70+
if (file.isDirectory()) {
71+
for (File subFile : Objects.requireNonNull(file.listFiles())) {
72+
addToZipFile(category + "/" + subFile.getName(), subFile, zos);
73+
}
74+
} else {
75+
try (FileInputStream fis = new FileInputStream(file)) {
76+
ZipEntry zipEntry = new ZipEntry(category + "/" + file.getName());
77+
zos.putNextEntry(zipEntry);
78+
79+
byte[] buffer = new byte[1024];
80+
int length;
81+
while ((length = fis.read(buffer)) > 0) {
82+
zos.write(buffer, 0, length);
83+
}
84+
zos.closeEntry();
85+
} catch (IOException e) {
86+
throw new RuntimeException(e);
87+
}
88+
}
89+
}
90+
91+
private record Source(String category, File file) {
92+
}
93+
}

0 commit comments

Comments
 (0)