aQute.bnd.main.DiffCommand Maven / Gradle / Ivy
The newest version!
package aQute.bnd.main;
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.File;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import aQute.bnd.build.Project;
import aQute.bnd.build.ProjectBuilder;
import aQute.bnd.differ.DiffPluginImpl;
import aQute.bnd.osgi.Builder;
import aQute.bnd.osgi.Constants;
import aQute.bnd.osgi.Instructions;
import aQute.bnd.osgi.Jar;
import aQute.bnd.osgi.Processor;
import aQute.bnd.service.diff.Delta;
import aQute.bnd.service.diff.Diff;
import aQute.bnd.service.diff.Differ;
import aQute.bnd.service.diff.Tree;
import aQute.configurable.Config;
import aQute.lib.getopt.Arguments;
import aQute.lib.getopt.Description;
import aQute.lib.getopt.Options;
import aQute.lib.io.IO;
import aQute.lib.tag.Tag;
public class DiffCommand {
private final static Logger logger = LoggerFactory.getLogger(DiffCommand.class);
bnd bnd;
DiffCommand(bnd bnd) {
this.bnd = bnd;
}
@Description("Compares two jars. Without specifying the JARs (and when there is a "
+ "current project) the jars of this project are diffed against their "
+ "baseline in the baseline repository, using the sub-builder's options (these can be overridden). "
+ "If one JAR is given, the tree is shown. Otherwise 2 JARs must be specified and they are "
+ "then compared to eachother.")
@Arguments(arg = {
"[newer file]", "[older file]"
})
interface diffOptions extends Options {
@Config(description = "Print the API")
boolean api();
@Config(description = "Print the Resources")
boolean resources();
@Config(description = "Print the Manifest")
boolean manifest();
@Config(description = "Show full tree")
boolean full();
@Config(description = "Print difference as valid XML")
boolean xml();
@Config(description = "Where to send the output")
File output();
@Config(description = "Limit to these packages (can have wildcards)")
Collection pack();
@Config(description = "Ignore headers")
Collection ignore();
}
public void diff(diffOptions options) throws Exception {
DiffPluginImpl di = new DiffPluginImpl();
List args = options._arguments();
if (args.size() == 0) {
Project project = bnd.getProject();
if (project != null) {
try (ProjectBuilder projectBuilder = project.getBuilder(null)) {
for (Builder b : projectBuilder.getSubBuilders()) {
ProjectBuilder pb = (ProjectBuilder) b;
Jar older = pb.getBaselineJar(); // make sure remains
// before
// disabling baselining
pb.setProperty(Constants.BASELINE, ""); // do not do
// baselining in
// build
Jar newer = pb.build();
di.setIgnore(pb.getProperty(Constants.DIFFIGNORE));
diff(options, di, newer, older);
bnd.getInfo(b);
}
}
bnd.getInfo(project);
return;
}
} else if (options._arguments()
.size() == 1) {
logger.debug("Show tree");
showTree(bnd, options);
return;
}
if (options._arguments()
.size() != 2) {
throw new IllegalArgumentException("Requires 2 jar files input");
}
Jar newer = bnd.getJar(args.get(0));
Jar older = bnd.getJar(args.get(1));
diff(options, di, newer, older);
}
private void diff(diffOptions options, DiffPluginImpl di, Jar newer, Jar older) throws Exception {
if (newer == null) {
bnd.error("No newer file specified");
return;
}
if (older == null) {
bnd.error("No older file specified");
return;
}
PrintWriter pw = null;
try {
File fout = options.output();
if (fout == null)
pw = IO.writer(bnd.out);
else
pw = IO.writer(fout, UTF_8);
Instructions packageFilters = new Instructions(options.pack());
if (options.ignore() != null)
di.setIgnore(Processor.join(options.ignore()));
Tree n = di.tree(newer);
Tree o = di.tree(older);
Diff diff = n.diff(o);
boolean all = options.api() == false && options.resources() == false && options.manifest() == false;
if (!options.xml()) {
if (all || options.api())
for (Diff packageDiff : diff.get("")
.getChildren()) {
if (packageFilters.matches(packageDiff.getName()))
show(pw, packageDiff, 0, !options.full());
}
if (all || options.manifest())
show(pw, diff.get(""), 0, !options.full());
if (all || options.resources())
show(pw, diff.get(""), 0, !options.full());
} else {
Tag tag = new Tag("diff");
tag.addAttribute("date", new Date());
tag.addContent(getTagFrom("newer", newer));
tag.addContent(getTagFrom("older", older));
if (all || options.api())
tag.addContent(getTagFrom(diff.get(""), !options.full()));
if (all || options.manifest())
tag.addContent(getTagFrom(diff.get(""), !options.full()));
if (all || options.resources())
tag.addContent(getTagFrom(diff.get(""), !options.full()));
pw.print("\n");
tag.print(0, pw);
}
} finally {
if (older != null) {
older.close();
}
if (newer != null) {
newer.close();
}
if (pw != null) {
pw.close();
}
}
}
/**
* Just show the single tree
*
* @param bnd
* @param options
* @throws Exception
*/
private static void showTree(bnd bnd, diffOptions options) throws Exception {
File fout = options.output();
PrintWriter pw;
if (fout == null)
pw = IO.writer(bnd.out);
else
pw = IO.writer(fout, UTF_8);
Instructions packageFilters = new Instructions(options.pack());
try (Jar newer = new Jar(bnd.getFile(options._arguments()
.get(0)))) {
Differ di = new DiffPluginImpl();
Tree n = di.tree(newer);
boolean all = options.api() == false && options.resources() == false && options.manifest() == false;
if (all || options.api())
for (Tree packageDiff : n.get("")
.getChildren()) {
if (packageFilters.matches(packageDiff.getName()))
show(pw, packageDiff, 0);
}
if (all || options.manifest())
show(pw, n.get(""), 0);
if (all || options.resources())
show(pw, n.get(""), 0);
} finally {
pw.close();
}
}
private static Tag getTagFrom(Diff diff, boolean limited) {
if (limited && (diff.getDelta() == Delta.UNCHANGED || diff.getDelta() == Delta.IGNORED))
return null;
Tag tag = new Tag("diff");
tag.addAttribute("name", diff.getName());
tag.addAttribute("delta", diff.getDelta());
tag.addAttribute("type", diff.getType());
if (limited && (diff.getDelta() == Delta.ADDED || diff.getDelta() == Delta.REMOVED))
return tag;
for (Diff c : diff.getChildren()) {
Tag child = getTagFrom(c, limited);
if (child != null)
tag.addContent(child);
}
return tag;
}
private static Tag getTagFrom(String name, Jar jar) throws Exception {
Tag tag = new Tag(name);
tag.addAttribute("bsn", jar.getBsn());
tag.addAttribute("name", jar.getName());
tag.addAttribute("version", jar.getVersion());
tag.addAttribute("lastmodified", jar.lastModified());
return tag;
}
public static void show(PrintWriter out, Diff diff, int indent, boolean limited) {
if (limited && (diff.getDelta() == Delta.UNCHANGED || diff.getDelta() == Delta.IGNORED))
return;
for (int i = 0; i < indent; i++)
out.print(" ");
out.println(diff.toString());
if (limited && (diff.getDelta() == Delta.ADDED || diff.getDelta() == Delta.REMOVED))
return;
for (Diff c : diff.getChildren()) {
show(out, c, indent + 1, limited);
}
}
public static void show(PrintWriter out, Tree tree, int indent) {
for (int i = 0; i < indent; i++)
out.print(" ");
out.println(tree.toString());
for (Tree c : tree.getChildren()) {
show(out, c, indent + 1);
}
}
}