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();
}
}