package org.bndtools.templating.jgit.ui; import java.io.FileNotFoundException; import java.lang.reflect.InvocationTargetException; import java.net.URI; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import org.bndtools.templating.jgit.Cache; import org.bndtools.templating.jgit.GitHub; import org.bndtools.templating.jgit.GitHubValidationException; import org.bndtools.templating.jgit.GithubRepoDetailsDTO; import org.bndtools.utils.jface.ProgressRunner; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.IMessageProvider; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.fieldassist.ControlDecoration; import org.eclipse.jface.fieldassist.FieldDecorationRegistry; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.swt.SWT; import org.eclipse.swt.events.ModifyEvent; import org.eclipse.swt.events.ModifyListener; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; import aQute.bnd.header.Attrs; import aQute.libg.tuple.Pair; public class GitHubRepoDialog extends AbstractNewEntryDialog { private final Cache cache = new Cache(); private final String title; private final ExecutorService executor; private String repository = null; private String branch = null; private Text txtRepository; private Text txtBranch; private volatile boolean isValidated = false; public GitHubRepoDialog(Shell parentShell, String title) { super(parentShell); this.title = title; setShellStyle(getShellStyle() | SWT.RESIZE); this.executor = Executors.newCachedThreadPool(); } @Override protected Control createDialogArea(Composite parent) { setTitle(title); Composite area = (Composite) super.createDialogArea(parent); Composite container = new Composite(area, SWT.NONE); container.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true)); container.setLayout(new GridLayout(2, false)); Label lblRepo = new Label(container, SWT.NONE); lblRepo.setText("Repository Name:"); txtRepository = new Text(container, SWT.BORDER); txtRepository.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); txtRepository.setMessage("username/repository"); if (repository != null) txtRepository.setText(repository); new Label(container, SWT.NONE).setText("Branch:"); txtBranch = new Text(container, SWT.BORDER); txtBranch.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false)); txtBranch.setMessage("default branch"); if (branch != null) txtBranch.setText(branch); ControlDecoration branchDecor = new ControlDecoration(txtBranch, SWT.LEFT, container); branchDecor.setDescriptionText("Specify the branch, tag or commit ID you would like to clone from the\nrepository. We use the default branch specified in GitHub settings."); branchDecor.setImage(FieldDecorationRegistry.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_INFORMATION).getImage()); branchDecor.setShowHover(true); final Button btnValidate = new Button(container, SWT.PUSH); btnValidate.setText("Validate"); btnValidate.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 2, 1)); ModifyListener modifyListener = new ModifyListener() { @Override public void modifyText(ModifyEvent ev) { if (!txtRepository.getText().trim().equals(repository)) { isValidated = false; repository = txtRepository.getText().trim(); } branch = txtBranch.getText().trim(); updateButtons(); } }; txtRepository.addModifyListener(modifyListener); txtBranch.addModifyListener(modifyListener); btnValidate.addSelectionListener(new SelectionAdapter() { @Override public void widgetSelected(SelectionEvent e) { setMessage(null, IMessageProvider.INFORMATION); try { if (repository == null || repository.isEmpty()) throw new GitHubValidationException("No repository name specified"); if (repository.contains(":/")) throw new GitHubValidationException("Specify GitHub repositories as username/repository"); IRunnableWithProgress runnable = new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { final GithubRepoDetailsDTO dto = new GitHub(cache, executor).loadRepoDetails(repository).getValue(); final URI cloneUri = URI.create(dto.clone_url); btnValidate.getDisplay().asyncExec(new Runnable() { @Override public void run() { setMessage(String.format("Validated! Clone URL is '%s'. Default branch 'origin/%s'", cloneUri, dto.default_branch), IMessageProvider.INFORMATION); isValidated = true; updateButtons(); } }); } catch (InvocationTargetException e) { throw e; } catch (Exception e) { throw new InvocationTargetException(e); } } }; ProgressRunner.execute(false, runnable, new ProgressMonitorDialog(getParentShell()), btnValidate.getDisplay()); setErrorMessage(null); } catch (InvocationTargetException ex) { Throwable t = ex.getCause(); if (t instanceof FileNotFoundException) setErrorMessage("Could not find the requested repository"); else setErrorMessage(t.getClass().getSimpleName() + ": " + t.getMessage()); } catch (GitHubValidationException ex) { setErrorMessage(ex.getMessage()); } catch (Exception ex) { setErrorMessage(ex.getClass().getSimpleName() + ": " + ex.getMessage()); } } }); return area; } @Override protected void createButtonsForButtonBar(Composite parent) { super.createButtonsForButtonBar(parent); Button ok = getButton(OK); ok.setText("Save"); ok.setEnabled(repository != null); } private void updateButtons() { getButton(OK).setEnabled(repository != null && !repository.trim().isEmpty() && isValidated); } @Override public void setEntry(Pair<String,Attrs> entry) { repository = entry.getFirst(); Attrs attrs = entry.getSecond(); branch = attrs.get("branch"); if (txtRepository != null && !txtRepository.isDisposed()) txtRepository.setText(repository); if (txtBranch != null && !txtBranch.isDisposed()) txtBranch.setText(branch); isValidated = true; } @Override public Pair<String,Attrs> getEntry() { Attrs attrs = new Attrs(); if (branch != null && !branch.trim().isEmpty()) attrs.put("branch", branch); return repository != null ? new Pair<String,Attrs>(repository.trim(), attrs) : null; } @Override public boolean close() { executor.shutdown(); return super.close(); } }