Skip to content

Commit

Permalink
Merge pull request #6285 from chrisrueger/extend-workspace-template-w…
Browse files Browse the repository at this point in the history
…izzard

Template fragments: show Author column and make it clear when you pull in content from non-bndtools / 3rd-party
  • Loading branch information
chrisrueger authored Oct 2, 2024
2 parents 4ccbd2f + db653e4 commit d3bd71e
Show file tree
Hide file tree
Showing 7 changed files with 190 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,27 @@ public enum UpdateStatus {
* Info about a template, comes from the index files.
*/

public record TemplateInfo(TemplateID id, String name, String description, String[] require, String... tag)
public record TemplateInfo(TemplateID id, String name, String description, String[] require,
String... tag)
implements Comparable<TemplateInfo> {

@Override
public int compareTo(TemplateInfo o) {
return id.compareTo(o.id);
}

/**
* @return <code>true</code> if this template is from the github
* bndtools organisation, which we consider "officially provided
* by us".
*/
public boolean isOfficial() {
return id.organisation()
.equals("bndtools");
}
}


public enum Action {
skip,
append,
Expand Down Expand Up @@ -191,7 +203,9 @@ public List<TemplateInfo> read(Parameters ps) {
* templates, see {@link #getAvailableTemplates()} internally maintained.
*/
public void add(TemplateInfo info) {
this.templates.add(info);
if (!templates.contains(info)) {
this.templates.add(info);
}
}

/**
Expand All @@ -211,7 +225,7 @@ public List<TemplateInfo> getAvailableTemplates() {
*/
public class TemplateUpdater implements AutoCloseable {
private static final String TOOL_BND = "tool.bnd";
final List<TemplateInfo> templates;
final List<TemplateInfo> templates;
final File folder;
final MultiMap<File, Update> updates = new MultiMap<>();
final List<AutoCloseable> closeables = new ArrayList<>();
Expand Down Expand Up @@ -278,11 +292,14 @@ public Map<File, List<Update>> updaters() {
}

List<Update> make(TemplateInfo template) {
Jar jar = getFiles(template.id()

TemplateID id = template.id();

Jar jar = getFiles(id
.uri());
closeables.add(jar);

String prefix = fixup(template.id()
String prefix = fixup(id
.path());

List<Update> updates = new ArrayList<>();
Expand Down
12 changes: 12 additions & 0 deletions biz.aQute.bndlib/src/aQute/bnd/wstemplates/TemplateID.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,17 @@ public URI uri() {
return URI.create(uri);
}

/**
* @return the url to the github repo source (without .zip extension)
*/
public String repoUrl() {
String uri = this.other;
if (uri == null) {
uri = "https://github.com/" + organisation + "/" + repository + "/tree/" + ref + "/" + path;
}
return uri;
}

/**
* Parse the id into a Template ID. The default is
* `bndtools/bndtools.workspace.min#master`. The missing fields are taken
Expand All @@ -74,6 +85,7 @@ public static TemplateID from(String id) {
String path = vs.getOrDefault("path", "");
if (!path.isEmpty())
path = path.substring(1);

String branch = vs.getOrDefault("branch", "master");
return new TemplateID(org, repo, path, branch, null);
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,27 @@ void testId() {
TemplateID other = TemplateID.from("file://z.zip");
assertThat(other.other()).isEqualTo("file://z.zip");

// tests a template at a specific commit SHA, which we do for 3rd party
// templates
// https://github.com/org/repo/tree/commitSHA/subfolder/workspace-template
// translates to the followingg templateID:
// org/repo/tree/commitSHA/subfolder/workspace-template/
TemplateID commitSHAUrl = TemplateID
.from("org/repo/subfolder/workspace-template#commitSHA");
assertThat(commitSHAUrl.organisation()).isEqualTo("org");
assertThat(commitSHAUrl.repository()).isEqualTo("repo");
assertThat(commitSHAUrl.path()).isEqualTo("subfolder/workspace-template");
assertThat(commitSHAUrl.repoUrl())
.isEqualTo("https://github.com/org/repo/tree/commitSHA/subfolder/workspace-template");

TemplateID defaultmasterUrl = TemplateID.from("org/repo/subfolder/workspace-template");
assertThat(defaultmasterUrl.repoUrl())
.isEqualTo("https://github.com/org/repo/tree/master/subfolder/workspace-template");

TemplateID defaultMasterUrl = TemplateID.from("org/repo/subfolder/workspace-template#master");
assertThat(defaultMasterUrl.repoUrl())
.isEqualTo("https://github.com/org/repo/tree/master/subfolder/workspace-template");

}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -1,25 +1,32 @@
package bndtools.wizards.newworkspace;

import static org.eclipse.jface.dialogs.MessageDialog.openConfirm;

import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.stream.Stream;

import org.bndtools.core.ui.icons.Icons;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.CheckboxTableViewer;
import org.eclipse.jface.viewers.ColumnLabelProvider;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.DoubleClickEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.TableLayout;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.Wizard;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.program.Program;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.DirectoryDialog;
Expand All @@ -29,6 +36,8 @@
import org.eclipse.ui.IImportWizard;
import org.eclipse.ui.INewWizard;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.forms.widgets.FormText;
import org.eclipse.ui.forms.widgets.ScrolledFormText;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -46,13 +55,19 @@
* Create a new Workspace Wizard.
*/
public class NewWorkspaceWizard extends Wizard implements IImportWizard, INewWizard {


static final String DEFAULT_INDEX = "https://raw.githubusercontent.com/bndtools/workspace-templates/master/index.bnd";
static final Logger log = LoggerFactory.getLogger(NewWorkspaceWizard.class);

final Model model = new Model();
final UI<Model> ui = new UI<>(model);
final NewWorkspaceWizardPage page = new NewWorkspaceWizardPage();
final FragmentTemplateEngine templates;
private ScrolledFormText txtDescription;

final static Image ok = Icons.image("icons/tick.png", false);
final static Image warn = Icons.image("icons/warning_obj.gif", false);

public NewWorkspaceWizard() throws Exception {
setWindowTitle("Create New bnd Workspace");
Expand Down Expand Up @@ -86,6 +101,23 @@ public void addPages() {

@Override
public boolean performFinish() {

// show a confirmation dialog
// if there is at least one 3rd-party template selected
long num3rdParty = model.selectedTemplates.stream()
.filter(t -> !t
.isOfficial())
.count();

boolean confirmed = num3rdParty == 0 || openConfirm(getShell(), "Install 3rd-Party templates",
"You have selected " + num3rdParty + " templates from 3rd-party authors. "
+ "Are you sure you trust the authors and want to continue fetching the content?");

if (!confirmed) {
// not confirmed. cancel selected
return false;
}

if (model.valid == null) {
ui.write(() -> {
TemplateUpdater updater = templates.updater(model.location, model.selectedTemplates);
Expand All @@ -94,6 +126,8 @@ public boolean performFinish() {
return true;
} else
return false;


}

class NewWorkspaceWizardPage extends WizardPage {
Expand Down Expand Up @@ -140,6 +174,19 @@ public void createControl(Composite parent) {
TableLayout tableLayout = new TableLayout();
table.setLayout(tableLayout);
table.setHeaderVisible(true);
selectedTemplates.addDoubleClickListener(new IDoubleClickListener() {
@Override
public void doubleClick(DoubleClickEvent e) {
// Handle double click event
IStructuredSelection selection = (IStructuredSelection) e.getSelection();
Object el = selection.getFirstElement();
if (el instanceof TemplateInfo sti) {
// Open URL in browser
Program.launch(sti.id()
.repoUrl());
}
}
});

TableViewerColumn nameColumn = new TableViewerColumn(selectedTemplates, SWT.NONE);
nameColumn.getColumn()
Expand All @@ -148,8 +195,8 @@ public void createControl(Composite parent) {

@Override
public String getText(Object element) {
if (element instanceof TemplateInfo) {
return ((TemplateInfo) element).name();
if (element instanceof TemplateInfo ti) {
return ti.name();
}
return super.getText(element);
}
Expand All @@ -162,19 +209,61 @@ public String getText(Object element) {

@Override
public String getText(Object element) {
if (element instanceof TemplateInfo) {
return ((TemplateInfo) element).description();
if (element instanceof TemplateInfo ti) {
return ti.description();
}
return super.getText(element);
}
});

TableViewerColumn authorColumn = new TableViewerColumn(selectedTemplates, SWT.NONE);
authorColumn.getColumn()
.setText("Author");
authorColumn.setLabelProvider(new ColumnLabelProvider() {

@Override
public String getText(Object element) {
if (element instanceof TemplateInfo ti) {
if (ti
.isOfficial()) {
return "bndtools (Official)";

}
else {
return ti.id()
.organisation() + " (3rd Party)";
}
}
return super.getText(element);
}

@Override
public Image getImage(Object element) {
if (element instanceof TemplateInfo ti) {
return ti
.isOfficial() ? ok : warn;
}

return super.getImage(element);
}

});


tableLayout.addColumnData(new ColumnWeightData(1, 80, false));
tableLayout.addColumnData(new ColumnWeightData(10, 200, true));
tableLayout.addColumnData(new ColumnWeightData(20, 80, true));

Button addButton = new Button(container, SWT.PUSH);
addButton.setText("+");
addButton.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, false, false, 2, 1));

txtDescription = new ScrolledFormText(container, SWT.V_SCROLL | SWT.H_SCROLL, false);
FormText formText = new FormText(txtDescription, SWT.NO_FOCUS);
txtDescription.setFormText(formText);
formText.setText("Double click to open the Github-Repo in your browser.", false, false);


ui.u("location", model.location, UI.text(location)
.map(File::getAbsolutePath, File::new));
ui.u("clean", model.clean, UI.checkbox(clean));
Expand Down Expand Up @@ -220,7 +309,7 @@ void addTemplate() {
TemplateDefinitionDialog dialog = new TemplateDefinitionDialog(getShell());
if (dialog.open() == Window.OK) {
String selectedPath = dialog.getSelectedPath();
if (!selectedPath.isBlank()) {
if (selectedPath != null && !selectedPath.isBlank()) {
Job job = Job.create("read " + selectedPath, mon -> {
try {
URI uri = toURI(selectedPath);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,10 +37,13 @@ protected Composite createDialogArea(Composite parent) {
container.setLayout(layout);

Label label = new Label(container, SWT.NONE);
label.setText("Template definitions. You can enter a URL or a file path");
label.setText(
"Template definitions. You can enter a URL or a file path");
label.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 12, 1));

Text textField = new Text(container, SWT.BORDER);
textField.setText(
"https://raw.githubusercontent.com/bndtools/workspace-templates/refs/heads/master/index.bnd");
GridData textFieldLayoutData = new GridData(SWT.FILL, SWT.CENTER, true, false, 11, 1);
textFieldLayoutData.minimumWidth = 200;
textField.setLayoutData(textFieldLayoutData);
Expand Down
Loading

0 comments on commit d3bd71e

Please sign in to comment.