Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New take on project export: now a zip file is generated which can be imported also #1209

Draft
wants to merge 45 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 42 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
5361e41
New take on projekt export, now a zip file is generated
BFH-ktt1 Oct 8, 2021
f4cdfb5
Made linter happy
BFH-ktt1 Oct 8, 2021
bc9607b
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 8, 2021
994f91f
First step in bundle export with user selactable added manifest
BFH-ktt1 Oct 10, 2021
225ea7f
Added placeholder for import and added a .info file to zip file
BFH-ktt1 Oct 10, 2021
110f28e
Reading and writing of information file
BFH-ktt1 Oct 10, 2021
da44bc7
Finished project bundle import option
BFH-ktt1 Oct 10, 2021
d994427
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 10, 2021
296ffaf
Small bugfix
BFH-ktt1 Oct 10, 2021
72861bc
Showing the manifest file when opening the file bundle and it contains a
BFH-ktt1 Oct 10, 2021
0c984e1
Code cleanup
BFH-ktt1 Oct 10, 2021
5055862
Only strip the unused libraries in case the option is set in
BFH-ktt1 Oct 10, 2021
a1da9b1
Added manifets writing phase 1
BFH-ktt1 Oct 11, 2021
edf8516
Bugfix
BFH-ktt1 Oct 11, 2021
362aaca
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 11, 2021
35371ec
Finished project export and manifest
BFH-ktt1 Oct 11, 2021
6f5b152
Updated changelog
BFH-ktt1 Oct 11, 2021
e385963
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 12, 2021
abda9ac
Updated changelog
BFH-ktt1 Oct 12, 2021
ca7ab71
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 14, 2021
c38b73c
Adressed reviewers comments
BFH-ktt1 Oct 14, 2021
7c72f28
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 15, 2021
5dfefe6
Renamed manifest to readme
BFH-ktt1 Oct 15, 2021
b20b290
Added always written manifest file
BFH-ktt1 Oct 15, 2021
7231e77
Adressed reviewers comments
BFH-ktt1 Oct 15, 2021
3621893
Fixed missed redundant remark lines
BFH-ktt1 Oct 15, 2021
d527eea
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 17, 2021
651752e
Removed save of project
BFH-ktt1 Oct 17, 2021
288b372
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 17, 2021
2ef20bc
As result of not forcing a save the the main-file could be null (no save
BFH-ktt1 Oct 17, 2021
0df7e82
Fixed last NPE
BFH-ktt1 Oct 17, 2021
942e0f2
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 17, 2021
09b1b7e
Updated changelog
BFH-ktt1 Oct 17, 2021
f590d10
Main circ file in bundle now has same name as the bundle
BFH-ktt1 Oct 17, 2021
84aed5b
Fixed README.md problem
BFH-ktt1 Oct 18, 2021
81c41af
Fixed manifest
BFH-ktt1 Oct 18, 2021
5f3e93b
Make linter happy
BFH-ktt1 Oct 18, 2021
1e2ad94
Extract and load project implemented
BFH-ktt1 Oct 18, 2021
e3de62c
Made linter happy
BFH-ktt1 Oct 18, 2021
d08bd22
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 19, 2021
bf2d8a6
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 20, 2021
fc7663e
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Oct 20, 2021
71a6e07
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Nov 7, 2021
e3276e8
Fixed missed conflict
BFH-ktt1 Nov 7, 2021
b293b35
Merge branch 'develop' of github.com:logisim-evolution/logisim-evolut…
BFH-ktt1 Jan 20, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

* @dev (????-??-??)
* Logisim has now an internal font-chooser to comply to the font-values used
* Fixed VHDL-component pins not visible bug
* New take on project export/import a zip-file is generated which can include a user provided "README.md"

* v3.7.0 (2021-10-12)
* Reworked the slider component in the I/O extra library
Expand All @@ -15,7 +17,7 @@
* `-clearprefs` is now `--clear-prefs`,
* `-clearprops` option is removed (use `--clear-prefs` instead),
* `-geom` is now `--geometry`,
* `-nosplash` is now `--no-splash` or `-ns,
* `-nosplash` is now `--no-splash` or `-ns`,
* `-sub` is now `--substitute` or `-s`,
* `-testvector` is now `--test-vector` or `-w`,
* `-test-fpga-implementation` is now `--test-fpga` or `-f`,
Expand All @@ -27,6 +29,7 @@
* Added a setting to select lower- or upper-case VHDL keywords.
* Added project export feature.
* Cleaned-up the written .circ file.
* Cleaned-up the library tree of loaded projects.

* v3.6.1 (2021-09-27)
* Fixed bug in LED-array
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ dependencies {
implementation("org.slf4j:slf4j-simple:1.7.30")
implementation("com.formdev:flatlaf:1.2")
implementation("commons-cli:commons-cli:1.4")
implementation("com.vladsch.flexmark:flexmark-all:0.62.2")

compileOnly("org.jetbrains:annotations:22.0.0")

Expand Down
12 changes: 11 additions & 1 deletion src/main/java/com/cburch/logisim/file/LibraryManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,17 @@ public Library loadLibrary(Loader loader, String desc) {
return null;
}
}


public static boolean isJarLibrary(Loader loader, String desc) {
final var sep = desc.indexOf(DESC_SEP);
if (sep < 0) {
loader.showError(S.get("fileDescriptorError", desc));
return false;
}
final var type = desc.substring(0, sep);
return "jar".equals(type);
}

public static String getLibraryFilePath(Loader loader, String desc) {
final var sep = desc.indexOf(DESC_SEP);
if (sep < 0) {
Expand Down
46 changes: 31 additions & 15 deletions src/main/java/com/cburch/logisim/file/Loader.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
import com.cburch.logisim.std.Builtin;
import com.cburch.logisim.tools.Library;
import com.cburch.logisim.util.JFileChoosers;
import com.cburch.logisim.util.LineBuffer;
import com.cburch.logisim.util.ZipClassLoader;
import com.cburch.logisim.vhdl.file.HdlFile;
import java.awt.Component;
Expand All @@ -28,6 +27,8 @@
import java.util.HashMap;
import java.util.Map;
import java.util.Stack;
import java.util.zip.ZipOutputStream;

import javax.swing.JFileChooser;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
Expand Down Expand Up @@ -82,6 +83,18 @@ public String getDescription() {
}
}

private static class LogisimProjectBundleFilter extends FileFilter {
@Override
public boolean accept(File f) {
return f.isDirectory() || f.getName().endsWith(LOGISIM_PROJECT_BUNDLE_EXTENSION);
}

@Override
public String getDescription() {
return S.get("logisimProjectBundleFilter");
}
}

private static class LogisimDirectoryFilter extends FileFilter {
@Override
public boolean accept(File f) {
Expand All @@ -107,9 +120,11 @@ public String getDescription() {
}

public static final String LOGISIM_EXTENSION = ".circ";
public static final String LOGISIM_LIBRARY_DIR = "library";
public static final String LOGISIM_CIRCUIT_DIR = "circuit";
public static final String LOGISIM_PROJECT_BUNDLE_EXTENSION = ".lsebdl";
public static final String LOGISIM_LIBRARY_DIR = "libraries";
public static final String LOGISIM_PROJECT_BUNDLE_INFO_FILE = "LogisimEvolutionBundle.info";
public static final FileFilter LOGISIM_FILTER = new LogisimFileFilter();
public static final FileFilter LOGISIM_BUNDLE_FILTER = new LogisimProjectBundleFilter();
public static final FileFilter LOGISIM_DIRECTORY = new LogisimDirectoryFilter();
public static final FileFilter JAR_FILTER = new JarFileFilter();
public static final FileFilter TXT_FILTER = new TxtFileFilter();
Expand All @@ -122,6 +137,7 @@ public String getDescription() {
private File mainFile = null;
private final Stack<File> filesOpening = new Stack<>();
private Map<File, File> substitutions = new HashMap<>();
private ZipOutputStream zipFile;

public Loader(Component parent) {
this.parent = parent;
Expand Down Expand Up @@ -326,21 +342,21 @@ public void reload(LoadedLibrary lib) {
LibraryManager.instance.reload(this, lib);
}

public boolean export(LogisimFile file, String homeDirectory) {
try {
final var mainCircFile = LineBuffer.format("{{1}}{{2}}{{3}}{{2}}{{4}}", homeDirectory, File.separator,
LOGISIM_CIRCUIT_DIR, getMainFile().getName());
final var libraryHome = String.format("%s%s%s", homeDirectory, File.separator, LOGISIM_LIBRARY_DIR);
final var fwrite = new FileOutputStream(mainCircFile);
file.write(fwrite, this, libraryHome);
} catch (IOException e) {
//TODO: give an error message to the user #1136
System.err.println("Unable to export file");
return false;
}
public boolean export(LogisimFile file, ZipOutputStream zipFile, String mainFileName) {
this.zipFile = zipFile;
file.write(zipFile, this, mainFileName);
this.zipFile = null;
return true;
}

public ZipOutputStream getZipFile() {
return zipFile;
}

public void setZipFile(ZipOutputStream file) {
zipFile = file;
}

public boolean save(LogisimFile file, File dest) {
final var reference = LibraryManager.instance.findReference(file, dest);
if (reference != null) {
Expand Down
22 changes: 17 additions & 5 deletions src/main/java/com/cburch/logisim/file/LogisimFile.java
Original file line number Diff line number Diff line change
Expand Up @@ -591,16 +591,24 @@ public void setName(String name) {
// other methods
//
void write(OutputStream out, LibraryLoader loader) {
write(out, loader, null, null);
write(out, loader, null, null, false);
}

void write(OutputStream out, LibraryLoader loader, String libraryHome) {
write(out, loader, null, libraryHome);
void write(OutputStream out, LibraryLoader loader, String mainCircFile) {
write(out, loader, null, mainCircFile, false);
}

void write(OutputStream out, LibraryLoader loader, File dest, String libraryHome) {
void write(OutputStream out, LibraryLoader loader, String mainCircFile, boolean recurse) {
write(out, loader, null, mainCircFile, recurse);
}

void write(OutputStream out, LibraryLoader loader, File dest, String mainCircFile) {
write(out, loader, dest, mainCircFile, false);
}

void write(OutputStream out, LibraryLoader loader, File dest, String mainCircFile, boolean recurse) {
try {
XmlWriter.write(this, out, loader, dest, libraryHome);
XmlWriter.write(this, out, loader, dest, mainCircFile, recurse);
} catch (TransformerConfigurationException e) {
loader.showError("internal error configuring transformer");
} catch (ParserConfigurationException e) {
Expand All @@ -610,6 +618,10 @@ void write(OutputStream out, LibraryLoader loader, File dest, String libraryHome
var err = S.get("xmlConversionError");
if (msg == null) err += ": " + msg;
loader.showError(err);
} catch (IOException e) {
loader.showError("Unable to create zip file");
} catch (LoadFailedException e) {
loader.showError("Unable to create zip file");
}
}

Expand Down
79 changes: 53 additions & 26 deletions src/main/java/com/cburch/logisim/file/XmlWriter.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,17 @@
import com.cburch.logisim.util.XmlUtil;
import com.cburch.logisim.vhdl.base.VhdlContent;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
Expand All @@ -64,29 +65,31 @@ final class XmlWriter {
* Path of the file which is being written on disk -- used to relativize components stored in it.
*/
private final String outFilePath;
private final String librariesPath;
private final boolean isProjectExport;
private final LibraryLoader loader;
private final HashMap<Library, String> libs = new HashMap<>();
private final boolean isRecursiveCall;

private XmlWriter(LogisimFile file, Document doc, LibraryLoader loader) {
this(file, doc, loader, null, null);
this(file, doc, loader, null, null, false);
}

private XmlWriter(LogisimFile file, Document doc, LibraryLoader loader, String outFilePath) {
this(file, doc, loader, outFilePath, null);
this(file, doc, loader, outFilePath, null, false);
}

private XmlWriter(LogisimFile file, Document doc, LibraryLoader loader, String outFilePath, String librariesPath) {
private XmlWriter(LogisimFile file, Document doc, LibraryLoader loader, String outFilePath,
String mainCircFile, boolean recursiveCall) {
this.file = file;
this.doc = doc;
this.loader = loader;
this.outFilePath = outFilePath;
this.librariesPath = librariesPath;
isProjectExport = StringUtil.isNotEmpty(librariesPath);
isProjectExport = StringUtil.isNotEmpty(mainCircFile);
isRecursiveCall = recursiveCall;
}



/* We sort some parts of the xml tree, to help with reproducibility and to
* ease testing (e.g. diff a circuit file). Attribute name=value pairs seem
* to be sorted already, so we don't worry about those. The code below sorts
Expand Down Expand Up @@ -172,8 +175,8 @@ static void sort(Node top) {
}
}

static void write(LogisimFile file, OutputStream out, LibraryLoader loader, File destFile, String libraryHome)
throws ParserConfigurationException, TransformerException {
static void write(LogisimFile file, OutputStream out, LibraryLoader loader, File destFile, String mainCircFile, boolean recurse)
throws ParserConfigurationException, TransformerException, IOException, LoadFailedException {

final var docFactory = XmlUtil.getHardenedBuilderFactory();
final var docBuilder = docFactory.newDocumentBuilder();
Expand All @@ -184,11 +187,9 @@ static void write(LogisimFile file, OutputStream out, LibraryLoader loader, File
var dstFilePath = destFile.getAbsolutePath();
dstFilePath = dstFilePath.substring(0, dstFilePath.lastIndexOf(File.separator));
context = new XmlWriter(file, doc, loader, dstFilePath);
} else if (libraryHome != null) {
context = new XmlWriter(file, doc, loader, null, libraryHome);
} else {
context = new XmlWriter(file, doc, loader);
}
} else if (mainCircFile != null) {
context = new XmlWriter(file, doc, loader, null, mainCircFile, recurse);
} else context = new XmlWriter(file, doc, loader);

context.fromLogisimFile();

Expand All @@ -207,6 +208,9 @@ static void write(LogisimFile file, OutputStream out, LibraryLoader loader, File
// Do nothing
}

if ((mainCircFile != null) && (out instanceof ZipOutputStream zipFile)) {
zipFile.putNextEntry(new ZipEntry(mainCircFile));
}
doc.normalize();
sort(doc);
Source src = new DOMSource(doc);
Expand Down Expand Up @@ -366,7 +370,7 @@ Element fromComponent(Component comp) {
return ret;
}

Element fromLibrary(Library lib) {
Element fromLibrary(Library lib) throws IOException, LoadFailedException {
final var ret = doc.createElement("lib");
if (libs.containsKey(lib)) return null;
final var name = Integer.toString(libs.size());
Expand All @@ -376,7 +380,7 @@ Element fromLibrary(Library lib) {
return null;
}
libs.put(lib, name);
if (isProjectExport || AppPreferences.REMOVE_UNUSED_LIBRARIES.getBoolean()) {
if (AppPreferences.REMOVE_UNUSED_LIBRARIES.getBoolean()) {
// first we check if the library is used and if this is not the case we do not add it
var isUsed = false;
final var tools = lib.getTools();
Expand All @@ -398,18 +402,22 @@ Element fromLibrary(Library lib) {
if (isProjectExport) {
if (lib instanceof LoadedLibrary) {
final var origFile = LibraryManager.getLibraryFilePath(file.getLoader(), desc);
final var isJarLibrary = LibraryManager.isJarLibrary(file.getLoader(), desc);
if (origFile != null) {
final var names = origFile.split(File.separator);
final var filename = names[names.length - 1];
final var newFile = String.format("%s%s%s", librariesPath, File.separator, filename);
try {
Files.copy(Paths.get(origFile), Paths.get(newFile), StandardCopyOption.REPLACE_EXISTING);
} catch (IOException e) {
//TODO: error message to user
return null;
final var newFile = LineBuffer.format("{{1}}{{2}}{{3}}", Loader.LOGISIM_LIBRARY_DIR, File.separator, filename);
final var zipFile = file.getLoader().getZipFile();
if (zipFile != null) {
if (isJarLibrary) {
writeJarToZip(zipFile, origFile, newFile);
} else {
writeLogisimFileToZip(zipFile, origFile, newFile);
}
desc = LibraryManager.getReplacementDescriptor(file.getLoader(), desc, isRecursiveCall
? LineBuffer.format(".{{1}}{{2}}", File.separator, filename)
: LineBuffer.format(".{{1}}{{2}}{{1}}{{3}}", File.separator, Loader.LOGISIM_LIBRARY_DIR, filename));
}
final var newFilePath = LineBuffer.format("..{{1}}{{2}}{{1}}{{3}}", File.separator, Loader.LOGISIM_LIBRARY_DIR, filename);
desc = LibraryManager.getReplacementDescriptor(file.getLoader(), desc, newFilePath);
}
}
}
Expand All @@ -429,7 +437,7 @@ Element fromLibrary(Library lib) {
return ret;
}

Element fromLogisimFile() {
Element fromLogisimFile() throws IOException, LoadFailedException {
final var ret = doc.createElement("project");
doc.appendChild(ret);
ret.appendChild(
Expand Down Expand Up @@ -536,4 +544,23 @@ boolean libraryContains(Library lib, Tool query) {
}
return false;
}

private void writeJarToZip(ZipOutputStream zipFile, String inputFileName, String outputFileName) throws IOException {
final var fileToRead = new File(inputFileName);
final var fileReader = new FileInputStream(fileToRead);
zipFile.putNextEntry(new ZipEntry(outputFileName));
final var bytes = new byte[1024];
var length = 0;
while ((length = fileReader.read(bytes)) >= 0) {
zipFile.write(bytes, 0, length);
}
fileReader.close();
}

private void writeLogisimFileToZip(ZipOutputStream zipFile, String inputFileName, String outputFileName) throws IOException, LoadFailedException {
final var newLoader = new Loader(null);
newLoader.setZipFile(zipFile);
final var library = newLoader.openLogisimFile(new File(inputFileName).getCanonicalFile());
library.write(zipFile, newLoader, outputFileName, true);
}
}