Merge branch 'master' into feature/multimeter3

This commit is contained in:
Bane Stojkovic
2025-03-20 21:16:55 +01:00
25 changed files with 1486 additions and 141 deletions
+52
View File
@@ -0,0 +1,52 @@
name: Java CI Tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Run Tests
run: mvn test
# Generate and report coverage without failing
- name: Generate Coverage Report
run: mvn jacoco:report
- name: Report Coverage
run: |
COVERAGE=$(mvn jacoco:report | grep -oP 'Total coverage: \K[0-9.]+' || echo "unknown")
echo "Current test coverage: $COVERAGE%"
- name: Upload Coverage Report
uses: actions/upload-artifact@v4
with:
name: coverage-report
path: target/site/jacoco/
retention-days: 5
# Optional: Comment test results on PR
- name: Add Test Results Comment
uses: marocchino/sticky-pull-request-comment@v2
if: github.event_name == 'pull_request'
with:
message: |
### Test Results Summary
✅ Tests completed
📊 Coverage: ${{ env.COVERAGE }}%
Coverage report available in workflow artifacts
+1 -1
View File
@@ -29,7 +29,7 @@ DIY Layout Creator (DIYLC) is a specialized software tool designed for hobbyists
<li>group components together and treat them as one, e.g. move, edit or delete </li> <li>group components together and treat them as one, e.g. move, edit or delete </li>
<li>export the output to image, PDF or printer </li> <li>export the output to image, PDF or printer </li>
<li>export PCB trace mask suitable for toner transfer </li> <li>export PCB trace mask suitable for toner transfer </li>
<li>export the circuit to a SPICE compatible netlist (beta) </li> <li>export PCB designs to Gerber for fabrication </li>
<li>create a Bill of Materials as a part of the project or export it to few different file formats </li> <li>create a Bill of Materials as a part of the project or export it to few different file formats </li>
<li>analyze guitar wirings and show detailed pickup configuration in each switch configuration</li> <li>analyze guitar wirings and show detailed pickup configuration in each switch configuration</li>
<li>zoom in/out feature </li> <li>zoom in/out feature </li>
BIN
View File
Binary file not shown.
+28
View File
@@ -0,0 +1,28 @@
name: Test Build
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
path: diy-layout-creator
- name: Set up JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'temurin'
cache: maven
- name: Build with Maven
run: |
cd diy-layout-creator/diylc
mvn -B test --file pom.xml
+51
View File
@@ -0,0 +1,51 @@
name: Java CI Tests
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
java-version: '11' # Adjust version as needed
distribution: 'temurin'
cache: maven
- name: Run Tests
run: mvn test
# Generate and report coverage without failing
- name: Generate Coverage Report
run: mvn jacoco:report
- name: Report Coverage
run: |
COVERAGE=$(mvn jacoco:report | grep -oP 'Total coverage: \K[0-9.]+' || echo "unknown")
echo "Current test coverage: $COVERAGE%"
- name: Upload Coverage Report
uses: actions/upload-artifact@v3
with:
name: coverage-report
path: target/site/jacoco/
# Optional: Comment test results on PR
- name: Add Test Results Comment
uses: marocchino/sticky-pull-request-comment@v2
if: github.event_name == 'pull_request'
with:
message: |
### Test Results Summary
✅ Tests completed
📊 Coverage: ${{ env.COVERAGE }}%
Coverage report available in workflow artifacts
+1
View File
@@ -0,0 +1 @@
[![Java CI Tests](https://github.com/{owner}/{repo}/actions/workflows/tests.yml/badge.svg)](https://github.com/{owner}/{repo}/actions/workflows/tests.yml)
-67
View File
@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" path="test"/>
<classpathentry kind="lib" path="lib/log4j-1.2.15.jar"/>
<classpathentry kind="lib" path="lib/junit-4.7.jar"/>
<classpathentry kind="lib" path="lib/app-framework.jar"/>
<classpathentry kind="lib" path="lib/jettison-1.0.1.jar"/>
<classpathentry kind="lib" path="lib/java-http-proxy.jar"/>
<classpathentry kind="lib" path="lib/AppleJavaExtensions.jar"/>
<classpathentry kind="lib" path="lib/xstream-1.4.19.jar"/>
<classpathentry kind="lib" path="lib/guava-31.1-jre.jar"/>
<classpathentry kind="lib" path="lib/gerber-writer-api-1.0.0.jar"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-17">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/classes" path="src/main/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/classes" path="src/main/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="src/test/java">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry excluding="**" kind="src" output="target/test-classes" path="src/test/resources">
<attributes>
<attribute name="maven.pomderived" value="true"/>
<attribute name="test" value="true"/>
<attribute name="optional" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.m2e.MAVEN2_CLASSPATH_CONTAINER">
<attributes>
<attribute name="maven.pomderived" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="target/generated-sources/annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" output="target/test-classes" path="target/generated-test-sources/test-annotations">
<attributes>
<attribute name="optional" value="true"/>
<attribute name="maven.pomderived" value="true"/>
<attribute name="ignore_optional_problems" value="true"/>
<attribute name="m2e-apt" value="true"/>
<attribute name="test" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="output" path="target/classes"/>
</classpath>
-23
View File
@@ -5,30 +5,7 @@
<projects> <projects>
</projects> </projects>
<buildSpec> <buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.m2e.core.maven2Builder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec> </buildSpec>
<natures> <natures>
<nature>org.eclipse.m2e.core.maven2Nature</nature>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures> </natures>
<filteredResources>
<filter>
<id>1741597028960</id>
<name></name>
<type>30</type>
<matcher>
<id>org.eclipse.core.resources.regexFilterMatcher</id>
<arguments>node_modules|\.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__</arguments>
</matcher>
</filter>
</filteredResources>
</projectDescription> </projectDescription>
-6
View File
@@ -92,11 +92,5 @@
<scope>system</scope> <scope>system</scope>
<systemPath>${project.basedir}/../lib/java-http-proxy.jar</systemPath> <systemPath>${project.basedir}/../lib/java-http-proxy.jar</systemPath>
</dependency> </dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>5.3.1</version>
<scope>test</scope>
</dependency>
</dependencies> </dependencies>
</project> </project>
@@ -25,7 +25,6 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import org.diylc.core.AllowAllValidator; import org.diylc.core.AllowAllValidator;
import org.diylc.core.IDynamicPropertySource;
import org.diylc.core.IPropertyValidator; import org.diylc.core.IPropertyValidator;
/** /**
@@ -0,0 +1,281 @@
/*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*/
package org.diylc.netlist;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.diylc.core.IDIYComponent;
public abstract class NetlistAnalyzer {
public NetlistAnalyzer() {
}
public List<Summary> summarize(List<Netlist> netlists, Node preferredOutput)
throws TreeException {
Map<String, Summary> summaries = new HashMap<String, Summary>();
for (Netlist n : netlists) {
Summary s = summarize(n, preferredOutput);
if (summaries.containsKey(s.getSummary()))
summaries.get(s.getSummary()).append(n);
else
summaries.put(s.getSummary(), s);
}
List<Summary> res = new ArrayList<Summary>(summaries.values());
Collections.sort(res);
return res;
}
protected abstract Summary summarize(Netlist netlist, Node preferredOutput) throws TreeException;
public Tree constructTreeBetween(Netlist netlist, Node nodeA, Node nodeB) {
Tree tree = new Tree(TreeConnectionType.Parallel);
connectNodes(netlist, nodeA, nodeB, tree.getChildren(), new Tree(TreeConnectionType.Series),
new HashSet<Node>());
return tree;
}
protected void connectNodes(Netlist netlist, Node nodeA, Node nodeB, List<Tree> concurrentPaths,
Tree currentPath, Set<Node> visited) {
if (nodeA == nodeB) {
concurrentPaths.add(currentPath);
return;
}
Group groupA = findGroup(netlist, nodeA);
if (groupA == null)
return;
if (groupA.getNodes().contains(nodeB)) {
concurrentPaths.add(currentPath);
return;
}
Set<Node> pathVisited = new HashSet<>(visited);
pathVisited.add(nodeA);
// First collect all immediate next nodes and their paths
Map<Node, List<Tree>> nextNodes = new HashMap<>();
for (Node n : groupA.getNodes()) {
if (pathVisited.contains(n))
continue;
IDIYComponent<?> c = n.getComponent();
for (int i = 0; i < c.getControlPointCount(); i++) {
int targetPoint = i;
int sourcePoint = n.getPointIndex();
if (targetPoint == sourcePoint)
continue;
if (c.getInternalLinkName(targetPoint, sourcePoint) != null) {
Node newNodeA = new Node(c, targetPoint, n.getZIndex());
if (pathVisited.contains(newNodeA))
continue;
try {
Tree newPath = (Tree) currentPath.clone();
TreeLeaf leaf = new TreeLeaf(c, targetPoint, sourcePoint);
Tree newItem = new Tree(leaf);
if (!newPath.getChildren().contains(newItem)) {
newPath.getChildren().add(newItem);
nextNodes.computeIfAbsent(newNodeA, k -> new ArrayList<>()).add(newPath);
}
} catch (CloneNotSupportedException e) {
// Skip this path if clone fails
}
}
}
}
// Now explore each next node
List<Tree> allPaths = new ArrayList<>();
for (Map.Entry<Node, List<Tree>> entry : nextNodes.entrySet()) {
for (Tree path : entry.getValue()) {
List<Tree> branchPaths = new ArrayList<>();
connectNodes(netlist, entry.getKey(), nodeB, branchPaths, path, pathVisited);
allPaths.addAll(branchPaths);
}
}
if (allPaths.isEmpty())
return;
if (allPaths.size() > 1) {
// Find common prefix among all paths
List<Tree> commonPrefix = findCommonElements(allPaths, true, false);
// Create a new tree for the merged result
Tree mergedTree = new Tree(TreeConnectionType.Series);
// Add common prefix elements
for (Tree prefixElement : commonPrefix) {
mergedTree.getChildren().add(prefixElement);
}
// Extract unique parts
List<Tree> uniqueParts = new ArrayList<>();
for (Tree path : allPaths) {
Tree uniquePart = extractUniquePart(path, commonPrefix.size(), 0);
if (uniquePart != null) {
if (uniquePart.getChildren().size() == 1) {
uniqueParts.add(uniquePart.getChildren().get(0));
} else {
uniqueParts.add(uniquePart);
}
}
}
// Create parallel section for unique parts
if (!uniqueParts.isEmpty()) {
Tree parallelSection = new Tree(TreeConnectionType.Parallel);
parallelSection.getChildren().addAll(uniqueParts);
// Add parallel section to series container
Tree parallelContainer = new Tree(TreeConnectionType.Series);
parallelContainer.getChildren().add(parallelSection);
mergedTree.getChildren().add(parallelContainer);
}
concurrentPaths.add(mergedTree);
} else {
concurrentPaths.add(allPaths.get(0));
}
}
private List<Tree> findCommonElements(List<Tree> paths, boolean fromStart, boolean backward) {
if (paths.isEmpty())
return new ArrayList<>();
List<Tree> common = new ArrayList<>();
Tree template = paths.get(0);
int maxLength = template.getChildren().size();
for (int i = 0; i < maxLength; i++) {
int index = fromStart ?
(backward ? template.getChildren().size() - i - 1 : i) :
(backward ? i : template.getChildren().size() - i - 1);
if (index < 0 || index >= template.getChildren().size())
break;
Tree element = template.getChildren().get(index);
boolean isCommon = true;
for (int j = 1; j < paths.size(); j++) {
Tree current = paths.get(j);
if (current.getChildren().size() <= i || index >= current.getChildren()
.size() || !current.getChildren().get(index).equals(element)) {
isCommon = false;
break;
}
}
if (isCommon) {
common.add(element);
} else {
break;
}
}
return common;
}
private Tree extractUniquePart(Tree path, int prefixSize, int suffixSize) {
if (path.getChildren().size() <= prefixSize + suffixSize)
return null;
Tree uniquePart = new Tree(TreeConnectionType.Series);
for (int i = prefixSize; i < path.getChildren().size() - suffixSize; i++) {
uniquePart.getChildren().add(path.getChildren().get(i));
}
return uniquePart.getChildren().isEmpty() ? null : uniquePart;
}
protected Group findGroup(Netlist netlist, Node node) {
for (Group g : netlist.getGroups())
if (g.getNodes().contains(node))
return g;
return null;
}
protected List<Node> find(Set<String> typeNames, String nodeName, Netlist netlist) {
List<Node> res = new ArrayList<Node>();
for (Group g : netlist.getGroups()) {
for (Node n : g.getNodes()) {
if (typeNames.contains(n.getComponent().getClass()
.getCanonicalName()) && (nodeName == null || n.getDisplayName()
.equalsIgnoreCase(nodeName))) {
res.add(n);
}
}
}
return res;
}
public static List<Set<IDIYComponent<?>>> extractComponentGroups(List<Netlist> netlists) {
List<Set<IDIYComponent<?>>> res = new ArrayList<Set<IDIYComponent<?>>>();
for (Netlist n : netlists) {
res.addAll(extractComponentGroups(n));
}
return res;
}
public static List<Set<IDIYComponent<?>>> extractComponentGroups(Netlist netlist) {
List<Set<IDIYComponent<?>>> res = new ArrayList<Set<IDIYComponent<?>>>();
for (Group g : netlist.getGroups()) {
Set<IDIYComponent<?>> components = new HashSet<IDIYComponent<?>>();
for (Node n : g.getNodes())
components.add(n.getComponent());
res.add(components);
}
return res;
}
protected int find(Node node, List<Group> groups) {
for (int i = 0; i < groups.size(); i++)
if (groups.get(i).getNodes().contains(node))
return i;
return -1;
}
protected boolean intersect(List<Group> groups, Node node) {
for (Group g : groups)
if (g.getNodes().contains(node))
return true;
return false;
}
protected Node intersect(List<Group> groups, Group group) {
for (Group g : groups)
for (Node node : group.getNodes())
if (g.getNodes().contains(node))
return node;
return null;
}
}
@@ -41,9 +41,16 @@ import org.diylc.common.IComponentTransformer;
import org.diylc.common.PropertyWrapper; import org.diylc.common.PropertyWrapper;
import org.diylc.core.CreationMethod; import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.core.IDynamicPropertySource; import org.diylc.core.IDynamicPropertySource;
import org.diylc.core.IPropertyValidator; import org.diylc.core.IPropertyValidator;
import org.diylc.core.annotations.*; import org.diylc.core.annotations.*;
import org.diylc.core.annotations.BomPolicy;
import org.diylc.core.annotations.ComponentDescriptor;
import org.diylc.core.annotations.EditableProperty;
import org.diylc.core.annotations.KeywordPolicy;
import org.diylc.lang.LangUtil; import org.diylc.lang.LangUtil;
/** /**
@@ -36,7 +36,9 @@ import org.apache.log4j.Logger;
import org.diylc.appframework.miscutils.ConfigurationManager; import org.diylc.appframework.miscutils.ConfigurationManager;
import org.diylc.clipboard.ComponentTransferable; import org.diylc.clipboard.ComponentTransferable;
import org.diylc.common.*; import org.diylc.common.*;
import org.diylc.core.Angle; import org.diylc.core.Angle;
import org.diylc.core.CreationMethod; import org.diylc.core.CreationMethod;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
+23 -7
View File
@@ -251,11 +251,6 @@
<changes> <changes>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType> <changeType>NEW_FEATURE</changeType>
<description>'Virtual Multimeter' from 'Analyze' menu traces the circuit finding all possible paths of electricity between two points designated by the probe symbol.</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added ability to highlight connected switch lugs in selected position in order to illustrate how it works internally.</description>
<description>Configurable 'High DPI Rendering' feature which makes the diagram smoother on high-resolution displays but can affect performance</description> <description>Configurable 'High DPI Rendering' feature which makes the diagram smoother on high-resolution displays but can affect performance</description>
</org.diylc.appframework.update.Change> </org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
@@ -272,10 +267,11 @@
</org.diylc.appframework.update.Change> </org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType> <changeType>IMPROVEMENT</changeType>
<description>Improved robustness of series/parallel graph construction code used in circuit analysis</description></org.diylc.appframework.update.Change> <description>Omit boards, wires, traces, terminals, etc from Spice netlist output</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>IMPROVEMENT</changeType> <changeType>IMPROVEMENT</changeType>
<description>Omit boards, wires, traces, terminals, etc from Spice netlist output</description> <description>Updated the windows installer to avoid false positive virus detection</description>
</org.diylc.appframework.update.Change> </org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change> <org.diylc.appframework.update.Change>
<changeType>BUG_FIX</changeType> <changeType>BUG_FIX</changeType>
@@ -288,5 +284,25 @@
</changes> </changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url> <url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version> </org.diylc.appframework.update.Version>
<org.diylc.appframework.update.Version>
<versionNumber>
<major>5</major>
<minor>2</minor>
<build>0</build>
</versionNumber>
<releaseDate>2025-03-20 00:00:00.000 CET</releaseDate>
<name></name>
<changes>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>'Virtual Multimeter' from 'Analyze' menu traces the circuit finding all possible paths of electricity between two points designated by the probe symbol.</description>
</org.diylc.appframework.update.Change>
<org.diylc.appframework.update.Change>
<changeType>NEW_FEATURE</changeType>
<description>Added ability to highlight connected switch lugs in selected position in order to illustrate how it works internally.</description>
</org.diylc.appframework.update.Change>
</changes>
<url>https://github.com/bancika/diy-layout-creator/releases</url>
</org.diylc.appframework.update.Version>
</a> </a>
</java.util.Arrays_-ArrayList> </java.util.Arrays_-ArrayList>
@@ -9,6 +9,9 @@ import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Test; import org.junit.Test;
import org.diylc.netlist.TreeAsciiUtil; import org.diylc.netlist.TreeAsciiUtil;
@@ -46,6 +46,14 @@ import org.diylc.components.passive.RadialFilmCapacitor;
import org.diylc.components.passive.RadialMicaCapacitor; import org.diylc.components.passive.RadialMicaCapacitor;
import org.diylc.components.passive.Resistor; import org.diylc.components.passive.Resistor;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.netlist.Netlist;
import org.diylc.netlist.NetlistAnalyzer;
import org.diylc.netlist.Node;
import org.diylc.netlist.Summary;
import org.diylc.netlist.Tree;
import org.diylc.netlist.TreeConnectionType;
import org.diylc.netlist.TreeException;
import org.diylc.netlist.TreeLeaf;
import org.diylc.netlist.Tree.ITreeWalker; import org.diylc.netlist.Tree.ITreeWalker;
public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements INetlistAnalyzer { public class GuitarDiagramAnalyzer extends AbstractNetlistAnalyzer implements INetlistAnalyzer {
@@ -27,6 +27,12 @@ import java.util.stream.Collectors;
import org.diylc.common.INetlistAnalyzer; import org.diylc.common.INetlistAnalyzer;
import org.diylc.core.IDIYComponent; import org.diylc.core.IDIYComponent;
import org.diylc.netlist.Group;
import org.diylc.netlist.Netlist;
import org.diylc.netlist.NetlistAnalyzer;
import org.diylc.netlist.Node;
import org.diylc.netlist.Summary;
import org.diylc.netlist.TreeException;
public class SpiceAnalyzer extends AbstractNetlistAnalyzer implements INetlistAnalyzer { public class SpiceAnalyzer extends AbstractNetlistAnalyzer implements INetlistAnalyzer {
@@ -21,8 +21,11 @@ package org.diylc.netlist;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import java.util.Arrays; import java.util.Arrays;
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
import org.diylc.components.passive.AxialFilmCapacitor; import org.diylc.components.passive.AxialFilmCapacitor;
import org.diylc.components.passive.Resistor; import org.diylc.components.passive.Resistor;
========
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
import org.junit.Test; import org.junit.Test;
import org.diylc.components.electromechanical.OpenJack1_4; import org.diylc.components.electromechanical.OpenJack1_4;
@@ -30,6 +33,14 @@ import org.diylc.components.guitar.HumbuckerPickup;
import org.diylc.components.guitar.SingleCoilPickup; import org.diylc.components.guitar.SingleCoilPickup;
import org.diylc.components.passive.PotentiometerPanel; import org.diylc.components.passive.PotentiometerPanel;
import org.diylc.components.passive.RadialCeramicDiskCapacitor; import org.diylc.components.passive.RadialCeramicDiskCapacitor;
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
========
import org.diylc.netlist.Group;
import org.diylc.netlist.GuitarDiagramAnalyzer;
import org.diylc.netlist.Netlist;
import org.diylc.netlist.Tree;
import org.diylc.netlist.TreeException;
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
public class GuitarDiagramAnalyzerTests { public class GuitarDiagramAnalyzerTests {
@@ -62,6 +73,7 @@ public class GuitarDiagramAnalyzerTests {
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist); Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString(); String s = tree.toString();
assertEquals("((Volume.1-2 + Pickup.North<-) || Volume.2-3)", s); assertEquals("((Volume.1-2 + Pickup.North<-) || Volume.2-3)", s);
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
} }
@Test @Test
@@ -105,6 +117,8 @@ public class GuitarDiagramAnalyzerTests {
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist); Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString(); String s = tree.toString();
assertEquals("(((Cbleed || Rbleed || Volume.1-2) + Pickup.North<-) || Volume.2-3)", s); assertEquals("(((Cbleed || Rbleed || Volume.1-2) + Pickup.North<-) || Volume.2-3)", s);
========
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
} }
@Test @Test
@@ -127,7 +141,11 @@ public class GuitarDiagramAnalyzerTests {
netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup).add(toneGroup); netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup).add(toneGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist); Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString(); String s = tree.toString();
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
assertEquals("((Volume.1-2 + ((Tone.2-3 + Cap) || Pickup.North<-)) || Volume.2-3)", s); assertEquals("((Volume.1-2 + ((Tone.2-3 + Cap) || Pickup.North<-)) || Volume.2-3)", s);
========
assertEquals("((Volume.1-2 + (Tone.2-3 + Cap) || Pickup.North<-) || Volume.2-3)", s);
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
} }
@Test @Test
@@ -161,7 +179,11 @@ public class GuitarDiagramAnalyzerTests {
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist); Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString(); String s = tree.toString();
assertEquals( assertEquals(
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
"((Volume.1-2 + (Pickup1.North<- || Pickup2.North<- || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2))) || Volume.2-3)", "((Volume.1-2 + (Pickup1.North<- || Pickup2.North<- || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2))) || Volume.2-3)",
========
"((Volume.1-2 + (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2) || Pickup1.North<- || Pickup2.North<-) || Volume.2-3)",
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
s); s);
} }
@@ -325,7 +347,11 @@ public class GuitarDiagramAnalyzerTests {
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist); Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString(); String s = tree.toString();
assertEquals( assertEquals(
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
"((Volume.1-2 + ((Pickup1.North<- + Pickup1.South<-) || (Pickup2.North<- + Pickup2.South<-) || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2))) || Volume.2-3)", "((Volume.1-2 + ((Pickup1.North<- + Pickup1.South<-) || (Pickup2.North<- + Pickup2.South<-) || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2))) || Volume.2-3)",
========
"((Volume.1-2 + (Pickup1.North<- + Pickup1.South<-) || (Pickup2.North<- + Pickup2.South<-) || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2)) || Volume.2-3)",
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
s); s);
} }
} }
@@ -0,0 +1,357 @@
/*
*
* DIY Layout Creator (DIYLC). Copyright (c) 2009-2018 held jointly by the individual authors.
*
* This file is part of DIYLC.
*
* DIYLC is free software: you can redistribute it and/or modify it under the terms of the GNU
* General Public License as published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* DIYLC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
* Public License for more details.
*
* You should have received a copy of the GNU General Public License along with DIYLC. If not, see
* <http://www.gnu.org/licenses/>.
*
*/
package org.diylc.netlist;
import static org.junit.Assert.assertEquals;
import java.util.Arrays;
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
import org.diylc.components.passive.AxialFilmCapacitor;
import org.diylc.components.passive.Resistor;
========
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
import org.junit.Test;
import org.diylc.components.electromechanical.OpenJack1_4;
import org.diylc.components.guitar.HumbuckerPickup;
import org.diylc.components.guitar.SingleCoilPickup;
import org.diylc.components.passive.PotentiometerPanel;
import org.diylc.components.passive.RadialCeramicDiskCapacitor;
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
========
import org.diylc.netlist.Group;
import org.diylc.netlist.GuitarDiagramAnalyzer;
import org.diylc.netlist.Netlist;
import org.diylc.netlist.Tree;
import org.diylc.netlist.TreeException;
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
public class GuitarDiagramAnalyzerTests {
@Test
public void testOneSinglePickup() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
SingleCoilPickup pickup = new SingleCoilPickup();
pickup.setName("Pickup");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup));
Group tipGroup = new Group().connect(jack, 0).connect(pickup, 1);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 2);
netlist.add(tipGroup).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("Pickup.North<-", s);
}
@Test
public void testOneSinglePickupVolPot() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
SingleCoilPickup pickup = new SingleCoilPickup();
pickup.setName("Pickup");
PotentiometerPanel vol = new PotentiometerPanel();
vol.setName("Volume");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup, vol));
Group hotGroup = new Group().connect(pickup, 1).connect(vol, 0);
Group tipGroup = new Group().connect(jack, 0).connect(vol, 1);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 2).connect(vol, 2);
netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("((Volume.1-2 + Pickup.North<-) || Volume.2-3)", s);
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
}
@Test
public void testOneSinglePickupVolPotTrebleBleedSeries() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
SingleCoilPickup pickup = new SingleCoilPickup();
pickup.setName("Pickup");
PotentiometerPanel vol = new PotentiometerPanel();
vol.setName("Volume");
AxialFilmCapacitor cap = new AxialFilmCapacitor();
cap.setName("Cbleed");
Resistor resistor = new Resistor();
resistor.setName("Rbleed");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup, vol));
Group hotGroup = new Group().connect(pickup, 1).connect(vol, 0).connect(resistor, 1);
Group tipGroup = new Group().connect(jack, 0).connect(vol, 1).connect(cap, 1);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 2).connect(vol, 2);
Group trebleBleedGroup = new Group().connect(cap, 0).connect(resistor, 0);
netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup).add(trebleBleedGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("((((Cbleed + Rbleed) || Volume.1-2) + Pickup.North<-) || Volume.2-3)", s);
}
@Test
public void testOneSinglePickupVolPotTrebleBleedParallel() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
SingleCoilPickup pickup = new SingleCoilPickup();
pickup.setName("Pickup");
PotentiometerPanel vol = new PotentiometerPanel();
vol.setName("Volume");
AxialFilmCapacitor cap = new AxialFilmCapacitor();
cap.setName("Cbleed");
Resistor resistor = new Resistor();
resistor.setName("Rbleed");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup, vol));
Group hotGroup = new Group().connect(pickup, 1).connect(vol, 0).connect(resistor, 1).connect(cap, 1);
Group tipGroup = new Group().connect(jack, 0).connect(vol, 1).connect(resistor, 0).connect(cap, 0);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 2).connect(vol, 2);
netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("(((Cbleed || Rbleed || Volume.1-2) + Pickup.North<-) || Volume.2-3)", s);
========
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
}
@Test
public void testOneSinglePickupVolTonePot() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
SingleCoilPickup pickup = new SingleCoilPickup();
pickup.setName("Pickup");
PotentiometerPanel vol = new PotentiometerPanel();
vol.setName("Volume");
PotentiometerPanel tone = new PotentiometerPanel();
tone.setName("Tone");
RadialCeramicDiskCapacitor cap = new RadialCeramicDiskCapacitor();
cap.setName("Cap");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup, vol, tone, cap));
Group hotGroup = new Group().connect(pickup, 1).connect(vol, 0).connect(tone, 2);
Group tipGroup = new Group().connect(jack, 0).connect(vol, 1);
Group sleeveGroup =
new Group().connect(jack, 1).connect(pickup, 2).connect(vol, 2).connect(cap, 0);
Group toneGroup = new Group().connect(tone, 1).connect(cap, 1);
netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup).add(toneGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
assertEquals("((Volume.1-2 + ((Tone.2-3 + Cap) || Pickup.North<-)) || Volume.2-3)", s);
========
assertEquals("((Volume.1-2 + (Tone.2-3 + Cap) || Pickup.North<-) || Volume.2-3)", s);
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
}
@Test
public void testTwoSinglePickupsMasterVolSeparateTone() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
SingleCoilPickup pickup1 = new SingleCoilPickup();
pickup1.setName("Pickup1");
SingleCoilPickup pickup2 = new SingleCoilPickup();
pickup2.setName("Pickup2");
PotentiometerPanel vol = new PotentiometerPanel();
vol.setName("Volume");
PotentiometerPanel tone1 = new PotentiometerPanel();
tone1.setName("Tone1");
PotentiometerPanel tone2 = new PotentiometerPanel();
tone2.setName("Tone2");
RadialCeramicDiskCapacitor cap1 = new RadialCeramicDiskCapacitor();
cap1.setName("Cap1");
RadialCeramicDiskCapacitor cap2 = new RadialCeramicDiskCapacitor();
cap2.setName("Cap2");
Netlist netlist =
new Netlist(Arrays.asList(jack, pickup1, pickup2, vol, tone1, tone2, cap1, cap2));
Group hotGroup = new Group().connect(pickup1, 1).connect(vol, 0).connect(tone1, 2)
.connect(pickup2, 1).connect(tone2, 2);
Group tipGroup = new Group().connect(jack, 0).connect(vol, 1);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup1, 2).connect(pickup2, 2)
.connect(vol, 2).connect(cap1, 0).connect(cap2, 0);
Group tone1Group = new Group().connect(tone1, 1).connect(cap1, 1);
Group tone2Group = new Group().connect(tone2, 1).connect(cap2, 1);
netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup).add(tone1Group)
.add(tone2Group);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals(
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
"((Volume.1-2 + (Pickup1.North<- || Pickup2.North<- || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2))) || Volume.2-3)",
========
"((Volume.1-2 + (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2) || Pickup1.North<- || Pickup2.North<-) || Volume.2-3)",
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
s);
}
@Test
public void testOneSinglePickupReverse() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
SingleCoilPickup pickup = new SingleCoilPickup();
pickup.setName("Pickup");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup));
Group tipGroup = new Group().connect(jack, 0).connect(pickup, 2);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 1);
netlist.add(tipGroup).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("Pickup.North->", s);
}
@Test
public void testOneHumbuckerSeries() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup = new HumbuckerPickup();
pickup.setName("Pickup");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup));
Group tipGroup = new Group().connect(jack, 0).connect(pickup, 0);
Group coilTapGroup = new Group().connect(pickup, 1).connect(pickup, 2);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 3);
netlist.add(tipGroup).add(coilTapGroup).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("(Pickup.North<- + Pickup.South<-)", s);
}
@Test
public void testOneHumbuckerSeriesReverse() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup = new HumbuckerPickup();
pickup.setName("Pickup");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup));
Group tipGroup = new Group().connect(jack, 0).connect(pickup, 3);
Group coilTapGroup = new Group().connect(pickup, 1).connect(pickup, 2);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 0);
netlist.add(tipGroup).add(coilTapGroup).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("(Pickup.South-> + Pickup.North->)", s);
}
@Test
public void testOneHumbuckerParallel() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup = new HumbuckerPickup();
pickup.setName("Pickup");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup));
Group tipGroup = new Group().connect(jack, 0).connect(pickup, 0).connect(pickup, 2);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 1).connect(pickup, 3);
netlist.add(tipGroup).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("(Pickup.North<- || Pickup.South<-)", s);
}
@Test
public void testOneHumbuckerParallelOutOfPhase() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup = new HumbuckerPickup();
pickup.setName("Pickup");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup));
Group tipGroup = new Group().connect(jack, 0).connect(pickup, 0).connect(pickup, 3);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup, 1).connect(pickup, 2);
netlist.add(tipGroup).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("(Pickup.North<- || Pickup.South->)", s);
}
@Test
public void testTwoHumbuckersSeries() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup1 = new HumbuckerPickup();
pickup1.setName("Pickup1");
HumbuckerPickup pickup2 = new HumbuckerPickup();
pickup2.setName("Pickup2");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup1, pickup2));
Group tipGroup = new Group().connect(jack, 0).connect(pickup1, 0);
Group coilTapGroup1 = new Group().connect(pickup1, 1).connect(pickup1, 2);
Group coilTapGroup2 = new Group().connect(pickup2, 1).connect(pickup2, 2);
Group joinGroup = new Group().connect(pickup1, 3).connect(pickup2, 0);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup2, 3);
netlist.add(tipGroup).add(coilTapGroup1).add(coilTapGroup2).add(joinGroup).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("(Pickup1.North<- + Pickup1.South<- + Pickup2.North<- + Pickup2.South<-)", s);
}
@Test
public void testTwoHumbuckersParallel() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup1 = new HumbuckerPickup();
pickup1.setName("Pickup1");
HumbuckerPickup pickup2 = new HumbuckerPickup();
pickup2.setName("Pickup2");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup1, pickup2));
Group tipGroup = new Group().connect(jack, 0).connect(pickup1, 0).connect(pickup2, 0);
Group coilTapGroup1 = new Group().connect(pickup1, 1).connect(pickup1, 2);
Group coilTapGroup2 = new Group().connect(pickup2, 1).connect(pickup2, 2);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup1, 3).connect(pickup2, 3);
netlist.add(tipGroup).add(coilTapGroup1).add(coilTapGroup2).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("((Pickup1.North<- + Pickup1.South<-) || (Pickup2.North<- + Pickup2.South<-))", s);
}
@Test
public void testTwoHumbuckersParallelOutOfPhase() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup1 = new HumbuckerPickup();
pickup1.setName("Pickup1");
HumbuckerPickup pickup2 = new HumbuckerPickup();
pickup2.setName("Pickup2");
Netlist netlist = new Netlist(Arrays.asList(jack, pickup1, pickup2));
Group tipGroup = new Group().connect(jack, 0).connect(pickup1, 0).connect(pickup2, 3);
Group coilTapGroup1 = new Group().connect(pickup1, 1).connect(pickup1, 2);
Group coilTapGroup2 = new Group().connect(pickup2, 1).connect(pickup2, 2);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup1, 3).connect(pickup2, 0);
netlist.add(tipGroup).add(coilTapGroup1).add(coilTapGroup2).add(sleeveGroup);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals("((Pickup1.North<- + Pickup1.South<-) || (Pickup2.South-> + Pickup2.North->))", s);
}
@Test
public void testTwoHumbuckersMasterVolSeparateTone() throws TreeException {
OpenJack1_4 jack = new OpenJack1_4();
HumbuckerPickup pickup1 = new HumbuckerPickup();
pickup1.setName("Pickup1");
HumbuckerPickup pickup2 = new HumbuckerPickup();
pickup2.setName("Pickup2");
PotentiometerPanel vol = new PotentiometerPanel();
vol.setName("Volume");
PotentiometerPanel tone1 = new PotentiometerPanel();
tone1.setName("Tone1");
PotentiometerPanel tone2 = new PotentiometerPanel();
tone2.setName("Tone2");
RadialCeramicDiskCapacitor cap1 = new RadialCeramicDiskCapacitor();
cap1.setName("Cap1");
RadialCeramicDiskCapacitor cap2 = new RadialCeramicDiskCapacitor();
cap2.setName("Cap2");
Netlist netlist =
new Netlist(Arrays.asList(jack, pickup1, pickup2, vol, tone1, tone2, cap1, cap2));
Group hotGroup = new Group().connect(pickup1, 0).connect(vol, 0).connect(tone1, 2)
.connect(pickup2, 0).connect(tone2, 2);
Group tipGroup = new Group().connect(jack, 0).connect(vol, 1);
Group sleeveGroup = new Group().connect(jack, 1).connect(pickup1, 3).connect(pickup2, 3)
.connect(vol, 2).connect(cap1, 0).connect(cap2, 0);
Group tone1Group = new Group().connect(tone1, 1).connect(cap1, 1);
Group tone2Group = new Group().connect(tone2, 1).connect(cap2, 1);
Group coilTap1 = new Group().connect(pickup1, 1).connect(pickup1, 2);
Group coilTap2 = new Group().connect(pickup2, 1).connect(pickup2, 2);
netlist.add(tipGroup).add(tipGroup).add(sleeveGroup).add(hotGroup).add(tone1Group)
.add(tone2Group).add(coilTap1).add(coilTap2);
Tree tree = new GuitarDiagramAnalyzer().constructTree(netlist);
String s = tree.toString();
assertEquals(
<<<<<<<< HEAD:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarDiagramAnalyzerTests.java
"((Volume.1-2 + ((Pickup1.North<- + Pickup1.South<-) || (Pickup2.North<- + Pickup2.South<-) || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2))) || Volume.2-3)",
========
"((Volume.1-2 + (Pickup1.North<- + Pickup1.South<-) || (Pickup2.North<- + Pickup2.South<-) || (Tone1.2-3 + Cap1) || (Tone2.2-3 + Cap2)) || Volume.2-3)",
>>>>>>>> master:diylc/diylc-library/src/test/java/org/diylc/netlist/GuitarNetlistAnalyzerTests.java
s);
}
}
+166
View File
@@ -0,0 +1,166 @@
# Setting up macOS Build Environment for DIYLC
This document describes how to set up a macOS machine for building and signing DIYLC application bundles.
## Prerequisites
1. **macOS System**
- macOS 11 (Big Sur) or later
- Xcode Command Line Tools installed
```bash
xcode-select --install
```
2. **Java Development Kit**
- Install JDK 17 (recommended to use SDKMAN!)
```bash
# Install SDKMAN!
curl -s "https://get.sdkman.io" | bash
source "$HOME/.sdkman/bin/sdkman-init.sh"
# Install JDK 17
sdk install java 17.0.14-tem
```
3. **Maven**
- Install Maven 3.9 or later
```bash
sdk install maven
```
## Apple Developer Account Setup
1. **Apple Developer Account**
- Enroll in the [Apple Developer Program](https://developer.apple.com/programs/)
- You need a paid membership ($99/year) for distribution signing
2. **Developer Certificate**
- Open Keychain Access
- Go to Certificate Assistant → Request a Certificate from a Certificate Authority
- Fill in your email and name
- Save to disk
- Go to [Apple Developer Certificates](https://developer.apple.com/account/resources/certificates/list)
- Create a new Developer ID Application certificate
- Download and double-click to install in Keychain
3. **Notarization Setup**
- Create an app-specific password:
1. Go to [Apple ID Account](https://appleid.apple.com/)
2. Security → App-Specific Passwords → Generate Password
3. Save this password securely
- Create a keychain profile for notarization:
```bash
xcrun notarytool store-credentials "AC_PASSWORD" \
--apple-id "your.email@example.com" \
--team-id "YOUR_TEAM_ID" \
--password "app-specific-password"
```
## Environment Configuration
1. **Set Developer Identity**
- Find your Developer ID in Keychain Access
```bash
security find-identity -v -p codesigning
```
- Set the environment variable (add to your ~/.zshrc):
```bash
export APPLE_DEVELOPER_IDENTITY="Developer ID Application: Your Name (TEAM_ID)"
```
2. **Verify Setup**
```bash
# Verify codesign is available
codesign --version
# Verify notarytool is available
xcrun notarytool --version
# Verify your identity is set
echo $APPLE_DEVELOPER_IDENTITY
```
## Building DIYLC
1. **Clone the Repository**
```bash
git clone https://github.com/bancika/diy-layout-creator.git
cd diy-layout-creator/diylc
```
2. **Build for Intel Macs**
```bash
mvn clean package -P mac-x86
```
3. **Build for Apple Silicon Macs**
```bash
mvn clean package -P mac-arm
```
4. **Build Both Architectures**
```bash
mvn clean package -P mac-x86,mac-arm
```
## Output Files
After successful builds, you'll find these files in the `diylc-swing/target` directory:
**Signed and Notarized Builds:**
- `diylc-<version>-osx-x86.zip` - Signed and notarized Intel build
- `diylc-<version>-osx-arm.zip` - Signed and notarized ARM build
**Unsigned Builds:**
- `diylc-<version>-osx-x86-unsigned.zip` - Unsigned Intel build
- `diylc-<version>-osx-arm-unsigned.zip` - Unsigned ARM build
The unsigned builds are created before the signing and notarization process and can be useful for testing or in environments where code signing is not required.
## Troubleshooting
1. **Signing Issues**
- Verify your certificate is valid:
```bash
security find-identity -v -p codesigning
```
- Check certificate expiration in Keychain Access
2. **Notarization Issues**
- Check notarization status:
```bash
xcrun notarytool log <submission-id> --keychain-profile "AC_PASSWORD"
```
- Verify entitlements are correct in `deploy/mac/entitlements.plist`
3. **Build Issues**
- Clear Maven cache:
```bash
rm -rf ~/.m2/repository/org/diylc
```
- Verify JDK version:
```bash
java -version
```
## Common Issues
1. **"The specified item could not be found in the keychain"**
- Solution: Verify your Developer ID certificate is in the keychain
- Check the exact name matches `APPLE_DEVELOPER_IDENTITY`
2. **"No account for team found"**
- Solution: Verify your Apple Developer membership is active
- Check team ID in notarytool credentials
3. **"The binary is not signed"**
- Solution: Check that the signing process isn't being skipped
- Verify all dependencies are properly signed
## Support
For additional help:
- Check the [Apple Code Signing Documentation](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution)
- File an issue on the DIYLC GitHub repository
- Contact the development team
+17
View File
@@ -0,0 +1,17 @@
Thank you for downloading DIY Layout Creator!
This app bundle is fully functional but not officially notarized by Apple.
To run it on your Mac, you'll need to approve it in the 'Privacy & Security' settings.
Without this approval, macOS will mark it as potentially damaged and prevent it from opening.
A notarized version is available, but due to Apple Developer Program costs and additional requirements,
it is exclusively offered to DIYLC Patreon supporters. For a small monthly membership fee,
you'll receive several benefits:
- Access to the notarized version
- Early access to upcoming features
- Voting rights to influence the development roadmap
- Direct developer support
Join our community at http://www.diy-fever.com/patreon
@@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>com.apple.security.cs.allow-jit</key>
<true/>
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
<true/>
<key>com.apple.security.cs.disable-library-validation</key>
<true/>
<key>com.apple.security.cs.debugger</key>
<true/>
<key>com.apple.security.get-task-allow</key>
<true/>
<key>com.apple.security.files.user-selected.read-write</key>
<true/>
<key>com.apple.security.files.downloads.read-write</key>
<true/>
</dict>
</plist>
+417 -16
View File
@@ -180,6 +180,17 @@
<configuration> <configuration>
<createDependencyReducedPom>false</createDependencyReducedPom> <createDependencyReducedPom>false</createDependencyReducedPom>
<finalName>diylc</finalName> <finalName>diylc</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>org.diylc.DIYLCStarter</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer"/>
</transformers>
<artifactSet>
<includes>
<include>*:*</include>
</includes>
</artifactSet>
<filters> <filters>
<filter> <filter>
<artifact>*:*</artifact> <artifact>*:*</artifact>
@@ -190,11 +201,104 @@
</excludes> </excludes>
</filter> </filter>
</filters> </filters>
<transformers> <minimizeJar>false</minimizeJar>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> <createSourcesJar>false</createSourcesJar>
<mainClass>org.diylc.DIYLCStarter</mainClass> <shadeSourcesContent>true</shadeSourcesContent>
</transformer> <dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
</transformers> </configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
</dependency>
</dependencies>
</plugin>
<!-- Add dependency plugin to copy system dependencies -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>copy-system-dependencies</id>
<phase>prepare-package</phase>
<goals>
<goal>copy-dependencies</goal>
</goals>
<configuration>
<includeScope>system</includeScope>
<outputDirectory>${project.build.directory}/system-libs</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!-- Add antrun plugin to include system dependencies in the final jar -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-antrun-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>merge-system-jars</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<unzip dest="${project.build.directory}/combined-classes">
<fileset dir="${project.build.directory}/system-libs" includes="*.jar"/>
</unzip>
<jar destfile="${project.build.directory}/diylc.jar" update="true">
<fileset dir="${project.build.directory}/combined-classes"/>
</jar>
</target>
</configuration>
</execution>
<execution>
<id>sign-jar-launcher</id>
<phase>package</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<target>
<!-- Extract JavaAppLauncher -->
<unzip src="${project.build.directory}/diylc.jar" dest="${project.build.directory}/jar-contents">
<patternset>
<include name="com/oracle/appbundler/JavaAppLauncher"/>
</patternset>
</unzip>
<!-- Make it executable -->
<chmod file="${project.build.directory}/jar-contents/com/oracle/appbundler/JavaAppLauncher" perm="755"/>
<!-- Sign the launcher -->
<exec executable="codesign" failonerror="true">
<arg value="--force"/>
<arg value="--sign"/>
<arg value="${env.APPLE_DEVELOPER_IDENTITY}"/>
<arg value="--timestamp"/>
<arg value="--options"/>
<arg value="runtime"/>
<arg value="--entitlements"/>
<arg value="${project.basedir}/deploy/mac/entitlements.plist"/>
<arg value="--all-architectures"/>
<arg value="--strict"/>
<arg value="--verbose"/>
<arg value="${project.build.directory}/jar-contents/com/oracle/appbundler/JavaAppLauncher"/>
</exec>
<!-- Update the jar with signed launcher -->
<jar destfile="${project.build.directory}/diylc.jar" update="true">
<fileset dir="${project.build.directory}/jar-contents"/>
</jar>
</target>
</configuration> </configuration>
</execution> </execution>
</executions> </executions>
@@ -304,20 +408,21 @@
compression="gzip" /> compression="gzip" />
<!-- Move extracted folder into AppImage location --> <!-- Move extracted folder into AppImage location -->
<mkdir dir="${appdir.jre}" /> <mkdir dir="${appdir.dir}/usr/bin/jre" />
<move todir="${appdir.jre}"> <move todir="${appdir.dir}/usr/bin/jre">
<fileset dir="${jre.dest.linux}/jdk-${jdk.version}-jre" /> <fileset dir="${jre.dest.linux}/jdk-${jdk.version}-jre" />
</move> </move>
<!-- Clean up temporary directory --> <!-- Clean up temporary directory -->
<delete dir="${jre.dest.linux}" /> <delete dir="${jre.dest.linux}" />
<echo message="JRE 17 bundled into ${appdir.jre}" /> <echo message="JRE 17 bundled into ${appdir.dir}/usr/bin/jre" />
<!-- Convert line endings to Unix format --> <!-- Update the launch script to use the correct JRE path -->
<fixcrlf file="${appdir.dir}/com.diy_fever.DIYLayoutCreator.desktop" eol="unix" /> <replace file="${appdir.dir}/usr/bin/diylc.sh">
<fixcrlf file="${appdir.dir}/AppRun" eol="unix" /> <replacetoken>JAVA_HOME="$APPDIR/usr/lib/jre"</replacetoken>
<fixcrlf file="${appdir.dir}/usr/bin/diylc.sh" eol="unix" /> <replacevalue>JAVA_HOME="$APPDIR/usr/bin/jre"</replacevalue>
</replace>
<echo message="AppDir structure created successfully at: ${appdir.dir}" /> <echo message="AppDir structure created successfully at: ${appdir.dir}" />
</target> </target>
@@ -554,7 +659,7 @@
<jdk.version.file>17.0.14_7</jdk.version.file> <jdk.version.file>17.0.14_7</jdk.version.file>
<jdk.archive.osx>OpenJDK17U-jre_x64_mac_hotspot_${jdk.version.file}.tar.gz</jdk.archive.osx> <jdk.archive.osx>OpenJDK17U-jre_x64_mac_hotspot_${jdk.version.file}.tar.gz</jdk.archive.osx>
<jdk.url.osx>https://github.com/adoptium/temurin17-binaries/releases/download/jdk-${jdk.version}/${jdk.archive.osx}</jdk.url.osx> <jdk.url.osx>https://github.com/adoptium/temurin17-binaries/releases/download/jdk-${jdk.version}/${jdk.archive.osx}</jdk.url.osx>
<jre.dest.osx>${project.build.directory}/jre_x86</jre.dest.osx> <jre.dest.osx>${project.build.directory}/jre_x86.bundle</jre.dest.osx>
</properties> </properties>
<build> <build>
<plugins> <plugins>
@@ -656,10 +761,158 @@
<option value="-Xdock:icon=Contents/Resources/diylc.icns"/> <option value="-Xdock:icon=Contents/Resources/diylc.icns"/>
</bundleapp> </bundleapp>
<!-- Create zip package --> <!-- First remove existing signatures -->
<echo message="Removing any existing signatures..."/>
<exec executable="codesign" failonerror="false">
<arg value="--remove-signature"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<echo message="Creating unsigned zip for distribution..."/>
<!-- Create unsigned zip for distribution -->
<zip destfile="${project.build.directory}/diylc-${project.version}-osx-x86-unsigned.zip">
<zipfileset filemode="755" dir="${project.build.directory}/DIYLC.app" prefix="DIYLC.app" />
<zipfileset dir="${project.basedir}/deploy/mac" includes="README.txt" />
</zip>
<echo message="Unsigned zip created at: ${project.build.directory}/diylc-${project.version}-osx-x86-unsigned.zip"/>
<!-- Sign the entire app bundle in one shot -->
<echo message="Signing complete app bundle..."/>
<exec executable="codesign" failonerror="true">
<arg value="--force"/>
<arg value="--sign"/>
<arg value="${env.APPLE_DEVELOPER_IDENTITY}"/>
<arg value="--timestamp"/>
<arg value="--options"/>
<arg value="runtime"/>
<arg value="--entitlements"/>
<arg value="${project.basedir}/deploy/mac/entitlements.plist"/>
<arg value="--deep"/>
<arg value="--all-architectures"/>
<arg value="--strict"/>
<arg value="--verbose"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<!-- Verify the signature -->
<echo message="Verifying code signature..."/>
<exec executable="codesign" failonerror="true">
<arg value="--verify"/>
<arg value="--deep"/>
<arg value="--verbose=4"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<echo message="Code signing completed successfully"/>
<echo message="Preparing zip archive for notarization..."/>
<!-- Create a ZIP archive for notarization -->
<zip destfile="${project.build.directory}/DIYLC-notarize.zip"
basedir="${project.build.directory}"
includes="DIYLC.app/**"/>
<echo message="Notarization archive created"/>
<!-- Submit for notarization -->
<echo message="Submitting app for notarization to Apple (this may take several minutes)..."/>
<exec executable="xcrun" outputproperty="submission.output" failonerror="true">
<arg value="notarytool"/>
<arg value="submit"/>
<arg value="${project.build.directory}/DIYLC-notarize.zip"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<!-- Extract UUID using string manipulation -->
<echo message="Notarization submission output: ${submission.output}"/>
<!-- Save output to a file for processing -->
<echo file="${project.build.directory}/notarization_output.txt" message="${submission.output}"/>
<!-- Use loadfile with filterchain to extract UUID -->
<loadfile property="notarization.uuid.raw" srcFile="${project.build.directory}/notarization_output.txt">
<filterchain>
<striplinebreaks/>
<tokenfilter>
<replaceregex pattern=".*id: ([a-f0-9-]{36}).*" replace="\1"/>
</tokenfilter>
</filterchain>
</loadfile>
<!-- Create clean UUID property without any whitespace -->
<loadresource property="notarization.uuid">
<propertyresource name="notarization.uuid.raw"/>
<filterchain>
<striplinebreaks/>
<tokenfilter>
<replaceregex pattern="\s+" replace=""/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="Raw UUID: '${notarization.uuid.raw}'"/>
<echo message="Clean UUID: '${notarization.uuid}'"/>
<!-- Wait for notarization with timeout -->
<echo message="Waiting for notarization to complete (this may take several minutes)..."/>
<exec executable="xcrun" resultproperty="wait.result" failonerror="false">
<arg value="notarytool"/>
<arg value="wait"/>
<arg value="${notarization.uuid}"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<!-- Check notarization status -->
<echo message="Checking final notarization status..."/>
<exec executable="xcrun" outputproperty="status.output" resultproperty="status.result" failonerror="false">
<arg value="notarytool"/>
<arg value="info"/>
<arg value="${notarization.uuid}"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<echo message="Notarization status output:${line.separator}${status.output}"/>
<!-- Get log regardless of status -->
<exec executable="xcrun" outputproperty="log.output" failonerror="false">
<arg value="notarytool"/>
<arg value="log"/>
<arg value="${notarization.uuid}"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<echo message="Detailed notarization log:${line.separator}${log.output}"/>
<!-- Check if status contains "Invalid" -->
<condition property="notarization.failed">
<contains string="${status.output}" substring="Invalid"/>
</condition>
<!-- Fail if notarization was invalid -->
<fail if="notarization.failed" message="Notarization failed. Please check the detailed log above for more information."/>
<!-- Only continue if notarization succeeded -->
<echo message="Notarization completed successfully. Proceeding with stapling..."/>
<!-- Sleep for a few seconds to ensure notarization is fully processed -->
<sleep seconds="10"/>
<echo message="Stapling notarization ticket to app bundle..."/>
<!-- Staple the notarization ticket -->
<exec executable="xcrun" failonerror="true">
<arg value="stapler"/>
<arg value="staple"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<echo message="Creating final signed and notarized zip package..."/>
<!-- Create final signed and notarized zip package -->
<zip destfile="${project.build.directory}/diylc-${project.version}-osx-x86.zip"> <zip destfile="${project.build.directory}/diylc-${project.version}-osx-x86.zip">
<zipfileset filemode="755" dir="${project.build.directory}/DIYLC.app" prefix="DIYLC.app" /> <zipfileset filemode="755" dir="${project.build.directory}/DIYLC.app" prefix="DIYLC.app" />
</zip> </zip>
<echo message="Final package created at: ${project.build.directory}/diylc-${project.version}-osx-x86.zip"/>
<echo message="Mac build process completed successfully!"/>
</target> </target>
</configuration> </configuration>
</execution> </execution>
@@ -676,7 +929,7 @@
<jdk.version.file>17.0.14_7</jdk.version.file> <jdk.version.file>17.0.14_7</jdk.version.file>
<jdk.archive.osx>OpenJDK17U-jre_aarch64_mac_hotspot_${jdk.version.file}.tar.gz</jdk.archive.osx> <jdk.archive.osx>OpenJDK17U-jre_aarch64_mac_hotspot_${jdk.version.file}.tar.gz</jdk.archive.osx>
<jdk.url.osx>https://github.com/adoptium/temurin17-binaries/releases/download/jdk-${jdk.version}/${jdk.archive.osx}</jdk.url.osx> <jdk.url.osx>https://github.com/adoptium/temurin17-binaries/releases/download/jdk-${jdk.version}/${jdk.archive.osx}</jdk.url.osx>
<jre.dest.osx>${project.build.directory}/jre_arm</jre.dest.osx> <jre.dest.osx>${project.build.directory}/jre_arm.bundle</jre.dest.osx>
</properties> </properties>
<build> <build>
<plugins> <plugins>
@@ -779,10 +1032,158 @@
<option value="-Xdock:icon=Contents/Resources/diylc.icns"/> <option value="-Xdock:icon=Contents/Resources/diylc.icns"/>
</bundleapp> </bundleapp>
<!-- Create zip package --> <!-- First remove existing signatures -->
<echo message="Removing any existing signatures..."/>
<exec executable="codesign" failonerror="false">
<arg value="--remove-signature"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<echo message="Creating unsigned zip for distribution..."/>
<!-- Create unsigned zip for distribution -->
<zip destfile="${project.build.directory}/diylc-${project.version}-osx-arm-unsigned.zip">
<zipfileset filemode="755" dir="${project.build.directory}/DIYLC.app" prefix="DIYLC.app" />
<zipfileset dir="${project.basedir}/deploy/mac" includes="README.txt" />
</zip>
<echo message="Unsigned zip created at: ${project.build.directory}/diylc-${project.version}-osx-arm-unsigned.zip"/>
<!-- Sign the entire app bundle in one shot -->
<echo message="Signing complete app bundle..."/>
<exec executable="codesign" failonerror="true">
<arg value="--force"/>
<arg value="--sign"/>
<arg value="${env.APPLE_DEVELOPER_IDENTITY}"/>
<arg value="--timestamp"/>
<arg value="--options"/>
<arg value="runtime"/>
<arg value="--entitlements"/>
<arg value="${project.basedir}/deploy/mac/entitlements.plist"/>
<arg value="--deep"/>
<arg value="--all-architectures"/>
<arg value="--strict"/>
<arg value="--verbose"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<!-- Verify the signature -->
<echo message="Verifying code signature..."/>
<exec executable="codesign" failonerror="true">
<arg value="--verify"/>
<arg value="--deep"/>
<arg value="--verbose=4"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<echo message="Code signing completed successfully"/>
<echo message="Preparing zip archive for notarization..."/>
<!-- Create a ZIP archive for notarization -->
<zip destfile="${project.build.directory}/DIYLC-notarize.zip"
basedir="${project.build.directory}"
includes="DIYLC.app/**"/>
<echo message="Notarization archive created"/>
<!-- Submit for notarization -->
<echo message="Submitting app for notarization to Apple (this may take several minutes)..."/>
<exec executable="xcrun" outputproperty="submission.output" failonerror="true">
<arg value="notarytool"/>
<arg value="submit"/>
<arg value="${project.build.directory}/DIYLC-notarize.zip"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<!-- Extract UUID using string manipulation -->
<echo message="Notarization submission output: ${submission.output}"/>
<!-- Save output to a file for processing -->
<echo file="${project.build.directory}/notarization_output.txt" message="${submission.output}"/>
<!-- Use loadfile with filterchain to extract UUID -->
<loadfile property="notarization.uuid.raw" srcFile="${project.build.directory}/notarization_output.txt">
<filterchain>
<striplinebreaks/>
<tokenfilter>
<replaceregex pattern=".*id: ([a-f0-9-]{36}).*" replace="\1"/>
</tokenfilter>
</filterchain>
</loadfile>
<!-- Create clean UUID property without any whitespace -->
<loadresource property="notarization.uuid">
<propertyresource name="notarization.uuid.raw"/>
<filterchain>
<striplinebreaks/>
<tokenfilter>
<replaceregex pattern="\s+" replace=""/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="Raw UUID: '${notarization.uuid.raw}'"/>
<echo message="Clean UUID: '${notarization.uuid}'"/>
<!-- Wait for notarization with timeout -->
<echo message="Waiting for notarization to complete (this may take several minutes)..."/>
<exec executable="xcrun" resultproperty="wait.result" failonerror="false">
<arg value="notarytool"/>
<arg value="wait"/>
<arg value="${notarization.uuid}"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<!-- Check notarization status -->
<echo message="Checking final notarization status..."/>
<exec executable="xcrun" outputproperty="status.output" resultproperty="status.result" failonerror="false">
<arg value="notarytool"/>
<arg value="info"/>
<arg value="${notarization.uuid}"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<echo message="Notarization status output:${line.separator}${status.output}"/>
<!-- Get log regardless of status -->
<exec executable="xcrun" outputproperty="log.output" failonerror="false">
<arg value="notarytool"/>
<arg value="log"/>
<arg value="${notarization.uuid}"/>
<arg value="--keychain-profile"/>
<arg value="AC_PASSWORD"/>
</exec>
<echo message="Detailed notarization log:${line.separator}${log.output}"/>
<!-- Check if status contains "Invalid" -->
<condition property="notarization.failed">
<contains string="${status.output}" substring="Invalid"/>
</condition>
<!-- Fail if notarization was invalid -->
<fail if="notarization.failed" message="Notarization failed. Please check the detailed log above for more information."/>
<!-- Only continue if notarization succeeded -->
<echo message="Notarization completed successfully. Proceeding with stapling..."/>
<!-- Sleep for a few seconds to ensure notarization is fully processed -->
<sleep seconds="10"/>
<echo message="Stapling notarization ticket to app bundle..."/>
<!-- Staple the notarization ticket -->
<exec executable="xcrun" failonerror="true">
<arg value="stapler"/>
<arg value="staple"/>
<arg value="${project.build.directory}/DIYLC.app"/>
</exec>
<echo message="Creating final signed and notarized zip package..."/>
<!-- Create final signed and notarized zip package -->
<zip destfile="${project.build.directory}/diylc-${project.version}-osx-arm.zip"> <zip destfile="${project.build.directory}/diylc-${project.version}-osx-arm.zip">
<zipfileset filemode="755" dir="${project.build.directory}/DIYLC.app" prefix="DIYLC.app" /> <zipfileset filemode="755" dir="${project.build.directory}/DIYLC.app" prefix="DIYLC.app" />
</zip> </zip>
<echo message="Final package created at: ${project.build.directory}/diylc-${project.version}-osx-arm.zip"/>
<echo message="Mac build process completed successfully!"/>
</target> </target>
</configuration> </configuration>
</execution> </execution>
Binary file not shown.
Binary file not shown.