diff --git a/org.archicontribs.modelrepository/.classpath b/org.archicontribs.modelrepository/.classpath index 735ab3b..bdd4c5f 100644 --- a/org.archicontribs.modelrepository/.classpath +++ b/org.archicontribs.modelrepository/.classpath @@ -4,7 +4,11 @@ - + + + + + diff --git a/org.archicontribs.modelrepository/META-INF/MANIFEST.MF b/org.archicontribs.modelrepository/META-INF/MANIFEST.MF index c290385..461b7c0 100644 --- a/org.archicontribs.modelrepository/META-INF/MANIFEST.MF +++ b/org.archicontribs.modelrepository/META-INF/MANIFEST.MF @@ -3,12 +3,13 @@ Bundle-ManifestVersion: 2 Bundle-Name: coArchi Bundle-SymbolicName: org.archicontribs.modelrepository;singleton:=true Bundle-Localization: plugin -Bundle-Version: 0.9.2.qualifier +Bundle-Version: 0.9.3.qualifier Bundle-Vendor: Archi Require-Bundle: org.eclipse.help.ui, - com.archimatetool.editor;bundle-version="4.9.0" + com.archimatetool.editor;bundle-version="4.9.0", + git-executor;bundle-version="1.0.0" Bundle-ActivationPolicy: lazy -Bundle-RequiredExecutionEnvironment: JavaSE-11 +Bundle-RequiredExecutionEnvironment: JavaSE-17 Eclipse-BundleShape: dir Bundle-Activator: org.archicontribs.modelrepository.ModelRepositoryPlugin Export-Package: org.archicontribs.modelrepository, diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/AbstractModelAction.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/AbstractModelAction.java index 9899daf..3279a04 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/AbstractModelAction.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/AbstractModelAction.java @@ -18,6 +18,7 @@ import org.archicontribs.modelrepository.grafico.IArchiRepository; import org.archicontribs.modelrepository.grafico.IRepositoryListener; import org.archicontribs.modelrepository.grafico.RepositoryListenerManager; +import org.archicontribs.modelrepository.grafico.ShellArchiRepository; import org.archicontribs.modelrepository.preferences.IPreferenceConstants; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.MessageDialog; @@ -36,24 +37,41 @@ public abstract class AbstractModelAction extends Action implements IGraficoMode private IArchiRepository fRepository; + private ShellArchiRepository shellRepository; + protected IWorkbenchWindow fWindow; protected AbstractModelAction(IWorkbenchWindow window) { fWindow = window; + + this.shellRepository = new ShellArchiRepository(); } @Override public void setRepository(IArchiRepository repository) { fRepository = repository; setEnabled(shouldBeEnabled()); + getShellRepository().setLocalRepoFolder(repository.getLocalRepositoryFolder()); } @Override public IArchiRepository getRepository() { return fRepository; } + + public boolean isShellModeAvailable() { + return this.shellRepository != null; + } - @Override + public void setShellRepository(ShellArchiRepository shellRepository) { + this.shellRepository = shellRepository; + } + + public ShellArchiRepository getShellRepository() { + return shellRepository; + } + + @Override public void update() { setEnabled(shouldBeEnabled()); } @@ -124,8 +142,12 @@ protected boolean offerToCommitChanges() { boolean amend = commitDialog.getAmend(); try { - getRepository().commitChanges(commitMessage, amend); - + if (isShellModeAvailable()) { + getShellRepository().commit(commitMessage, amend); + } else { + getRepository().commitChanges(commitMessage, amend); + + } // Save the checksum getRepository().saveChecksum(); } diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RefreshModelAction.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RefreshModelAction.java index bb7466a..253c7ab 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RefreshModelAction.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RefreshModelAction.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.security.GeneralSecurityException; +import java.util.logging.Logger; import org.archicontribs.modelrepository.IModelRepositoryImages; import org.archicontribs.modelrepository.authentication.ProxyAuthenticator; @@ -18,6 +19,7 @@ import org.archicontribs.modelrepository.grafico.GraficoModelLoader; import org.archicontribs.modelrepository.grafico.GraficoUtils; import org.archicontribs.modelrepository.grafico.IRepositoryListener; +import org.archicontribs.modelrepository.grafico.ShellArchiRepository.PullOutcome; import org.archicontribs.modelrepository.merge.MergeConflictHandler; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.dialogs.MessageDialog; @@ -51,7 +53,7 @@ * @author Phillip Beauvoir */ public class RefreshModelAction extends AbstractModelAction { - + protected static final int PULL_STATUS_ERROR = -1; protected static final int PULL_STATUS_OK = 0; protected static final int PULL_STATUS_UP_TO_DATE = 1; @@ -59,6 +61,8 @@ public class RefreshModelAction extends AbstractModelAction { protected static final int USER_OK = 0; protected static final int USER_CANCEL = 1; + + private static final Logger LOGGER = Logger.getLogger(RefreshModelAction.class.getName()); public RefreshModelAction(IWorkbenchWindow window) { super(window); @@ -66,11 +70,12 @@ public RefreshModelAction(IWorkbenchWindow window) { setText(Messages.RefreshModelAction_0); setToolTipText(Messages.RefreshModelAction_0); } - + public RefreshModelAction(IWorkbenchWindow window, IArchimateModel model) { this(window); + if(model != null) { - setRepository(new ArchiRepository(GraficoUtils.getLocalRepositoryFolderForModel(model))); + setRepository(new ArchiRepository(GraficoUtils.getLocalRepositoryFolderForModel(model))); } } @@ -169,7 +174,8 @@ protected int init() throws IOException, GitAPIException { getRepository().exportModelToGraficoFiles(); // Then offer to Commit - if(getRepository().hasChangesToCommit()) { + if((super.isShellModeAvailable() && super.getShellRepository().hasChanges()) + || getRepository().hasChangesToCommit()) { if(!offerToCommitChanges()) { return USER_CANCEL; } @@ -186,7 +192,21 @@ protected int pull(UsernamePassword npw, ProgressMonitorDialog pmDialog) throws Display.getCurrent().readAndDispatch(); // update dialog try { - pullResult = getRepository().pullFromRemote(npw, new ProgressMonitorWrapper(pmDialog.getProgressMonitor())); + if (super.isShellModeAvailable()) { + PullOutcome pullOutcome = super.getShellRepository().pullFromRemote(npw); + switch(pullOutcome) { + case ALREADY_UP_TO_DATE: + return PULL_STATUS_UP_TO_DATE; + case PULLED_SUCCESSFULLY: + // places loaded in model in IEditorModelManager + new GraficoModelLoader(getRepository()).loadModel(); + return PULL_STATUS_OK; + case PULL_INCOMPLETE: + LOGGER.warning("Shell mode run into trouble, falling back to jgit handlings."); + } + } + + pullResult = getRepository().pullFromRemote(npw, new ProgressMonitorWrapper(pmDialog.getProgressMonitor())); } catch(Exception ex) { // If this exception is thrown then the remote doesn't have the ref which can happen when pulling on a branch, @@ -289,7 +309,6 @@ protected int pull(UsernamePassword npw, ProgressMonitorDialog pmDialog) throws commitMessage += "\n\n" + Messages.RefreshModelAction_3 + "\n" + restoredObjects; //$NON-NLS-1$ //$NON-NLS-2$ } - // TODO - not sure if amend should be false or true here? getRepository().commitChanges(commitMessage, false); } diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RestoreCommitAction.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RestoreCommitAction.java index 6b5cfa5..cd15b89 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RestoreCommitAction.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/actions/RestoreCommitAction.java @@ -35,7 +35,7 @@ public class RestoreCommitAction extends AbstractModelAction { public RestoreCommitAction(IWorkbenchWindow window) { super(window); - setImageDescriptor(IModelRepositoryImages.ImageFactory.getImageDescriptor(IModelRepositoryImages.ICON_SYNCED)); + setImageDescriptor(IModelRepositoryImages.ImageFactory.getImageDescriptor(IModelRepositoryImages.ICON_RESET)); setText(Messages.RestoreCommitAction_0); setToolTipText(Messages.RestoreCommitAction_0); } diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/authentication/ProxyAuthenticator.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/authentication/ProxyAuthenticator.java index 1da9233..ac8d51d 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/authentication/ProxyAuthenticator.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/authentication/ProxyAuthenticator.java @@ -15,6 +15,7 @@ import java.net.ProxySelector; import java.net.SocketAddress; import java.net.URI; +import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; import java.security.GeneralSecurityException; @@ -170,12 +171,12 @@ private static Proxy createHTTPProxyFromPreferences() { /** * Test a http connection */ - public static boolean testHTTPConnection(String url) throws IOException { + public static boolean testHTTPConnection(String url) throws IOException, URISyntaxException { if(GraficoUtils.isSSH(url)) { return false; } - URL testURL = new URL(url); + URL testURL = new URI(url).toURL(); // localhost https connections throw certificate exceptions if("localhost".equals(testURL.getHost()) || "127.0.0.1".equals(testURL.getHost())) { //$NON-NLS-1$ //$NON-NLS-2$ diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/AddBranchDialog.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/AddBranchDialog.java index 65c1d8f..c994bb5 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/AddBranchDialog.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/AddBranchDialog.java @@ -23,6 +23,7 @@ import org.eclipse.swt.widgets.Text; import com.archimatetool.editor.ui.IArchiImages; +import com.archimatetool.editor.ui.UIUtils; /** * Add Branch Dialog @@ -98,7 +99,7 @@ private Text createTextField(Composite container, String message, int style) { Label label = new Label(container, SWT.NONE); label.setText(message); - Text txt = new Text(container, SWT.BORDER | style); + Text txt = UIUtils.createSingleTextControl(container, SWT.BORDER | style, false); txt.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return txt; diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/CloneInputDialog.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/CloneInputDialog.java index 7ec9666..56c6677 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/CloneInputDialog.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/CloneInputDialog.java @@ -24,6 +24,7 @@ import org.eclipse.swt.widgets.Text; import com.archimatetool.editor.ui.IArchiImages; +import com.archimatetool.editor.ui.UIUtils; /** * Clone Input Dialog @@ -89,7 +90,7 @@ protected Text createTextField(Composite container, String message, int style) { Label label = new Label(container, SWT.NONE); label.setText(message); - Text txt = new Text(container, SWT.BORDER | style); + Text txt = UIUtils.createSingleTextControl(container, SWT.BORDER | style, false); txt.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return txt; diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/UserNamePasswordDialog.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/UserNamePasswordDialog.java index 47f8dfa..12ae092 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/UserNamePasswordDialog.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/dialogs/UserNamePasswordDialog.java @@ -25,6 +25,7 @@ import org.eclipse.swt.widgets.Text; import com.archimatetool.editor.ui.IArchiImages; +import com.archimatetool.editor.ui.UIUtils; /** * User Name and Password Dialog @@ -77,7 +78,7 @@ private Text createTextField(Composite container, String message, int style) { Label label = new Label(container, SWT.NONE); label.setText(message); - Text txt = new Text(container, SWT.BORDER | style); + Text txt = UIUtils.createSingleTextControl(container, SWT.BORDER | style, false); txt.setLayoutData(new GridData(GridData.FILL_HORIZONTAL)); return txt; diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/GraficoFileConventions.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/GraficoFileConventions.java new file mode 100644 index 0000000..5c74484 --- /dev/null +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/GraficoFileConventions.java @@ -0,0 +1,40 @@ +package org.archicontribs.modelrepository.grafico; + +import java.io.File; + +import org.eclipse.emf.ecore.EObject; + +import com.archimatetool.model.FolderType; +import com.archimatetool.model.IFolder; +import com.archimatetool.model.IIdentifier; + +public final class GraficoFileConventions { + + private GraficoFileConventions() { + // utility class + } + + public static File forFolder(File parentFolder, IFolder iFolder) { + return new File(parentFolder, GraficoFileConventions.getNameFor(iFolder)); + } + + public static File forElement(File modelFolder, IFolder iFolder, EObject elem) { + File elemFolder = new File(modelFolder, GraficoFileConventions.getNameFor(iFolder)); + return GraficoFileConventions.forElement(elemFolder, elem); + } + + public static File forElement(File elemFolder, EObject elem) { + return new File(elemFolder, elem.getClass().getSimpleName() + "_" + ((IIdentifier) elem).getId() + ".xml"); //$NON-NLS-1$ //$NON-NLS-2$ + } + + /** + * Generate a proper name for directory creation + * + * @param folder + * @return + */ + public static String getNameFor(IFolder folder) { + return folder.getType() == FolderType.USER ? folder.getId().toString() : folder.getType().toString(); + } + +} diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/GraficoModelExporter.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/GraficoModelExporter.java index 3d81acf..a9c8ba8 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/GraficoModelExporter.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/GraficoModelExporter.java @@ -36,12 +36,10 @@ import com.archimatetool.editor.model.IArchiveManager; import com.archimatetool.editor.utils.FileUtils; -import com.archimatetool.model.FolderType; import com.archimatetool.model.IArchimateModel; import com.archimatetool.model.IDiagramModelImageProvider; import com.archimatetool.model.IFolder; import com.archimatetool.model.IFolderContainer; -import com.archimatetool.model.IIdentifier; /** @@ -177,7 +175,7 @@ private void createAndSaveResourceForFolder(IFolderContainer folderContainer, Fi allFolders.addAll(folderContainer.getFolders()); for(IFolder tmpFolder : allFolders) { - File tmpFolderFile = new File(folder, getNameFor(tmpFolder)); + File tmpFolderFile = GraficoFileConventions.forFolder(folder, tmpFolder); tmpFolderFile.mkdirs(); createAndSaveResource(new File(tmpFolderFile, IGraficoConstants.FOLDER_XML), tmpFolder); createAndSaveResourceForFolder(tmpFolder, tmpFolderFile); @@ -190,7 +188,7 @@ private void createAndSaveResourceForFolder(IFolderContainer folderContainer, Fi allElements.addAll(((IFolder)folderContainer).getElements()); for(EObject tmpElement : allElements) { createAndSaveResource( - new File(folder, tmpElement.getClass().getSimpleName() + "_" + ((IIdentifier)tmpElement).getId() + ".xml"), //$NON-NLS-1$ //$NON-NLS-2$ + GraficoFileConventions.forElement(folder, tmpElement), tmpElement); } } @@ -198,17 +196,7 @@ private void createAndSaveResourceForFolder(IFolderContainer folderContainer, Fi createAndSaveResource(new File(folder, IGraficoConstants.FOLDER_XML), folderContainer); } } - - /** - * Generate a proper name for directory creation - * - * @param folder - * @return - */ - private String getNameFor(IFolder folder) { - return folder.getType() == FolderType.USER ? folder.getId().toString() : folder.getType().toString(); - } - + /** * Save the model to Resource * diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/RepositoryListenerManager.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/RepositoryListenerManager.java index 5a316ca..2bc901c 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/RepositoryListenerManager.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/RepositoryListenerManager.java @@ -6,12 +6,9 @@ package org.archicontribs.modelrepository.grafico; import java.beans.PropertyChangeEvent; -import java.util.ArrayList; -import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; -import org.eclipse.core.runtime.SafeRunner; import org.eclipse.emf.common.notify.Notification; -import org.eclipse.jface.util.SafeRunnable; import com.archimatetool.editor.model.IEditorModelManager; import com.archimatetool.model.IArchimateModel; @@ -26,7 +23,7 @@ public class RepositoryListenerManager { public static final RepositoryListenerManager INSTANCE = new RepositoryListenerManager(); - private List listeners = new ArrayList(); + private CopyOnWriteArrayList listeners = new CopyOnWriteArrayList<>(); private RepositoryListenerManager() { // Listen to open model changes @@ -34,9 +31,7 @@ private RepositoryListenerManager() { } public void addListener(IRepositoryListener listener) { - if(!listeners.contains(listener)) { - listeners.add(listener); - } + listeners.addIfAbsent(listener); } public void removeListener(IRepositoryListener listener) { @@ -49,12 +44,7 @@ public void fireRepositoryChangedEvent(String eventName, IArchiRepository reposi } for(IRepositoryListener listener : listeners) { - SafeRunner.run(new SafeRunnable() { - @Override - public void run() { - listener.repositoryChanged(eventName, repository); - } - }); + listener.repositoryChanged(eventName, repository); } } diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/ShellArchiRepository.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/ShellArchiRepository.java new file mode 100644 index 0000000..f9519fa --- /dev/null +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/grafico/ShellArchiRepository.java @@ -0,0 +1,76 @@ +package org.archicontribs.modelrepository.grafico; + +import java.io.File; +import java.io.IOException; + +import org.archicontribs.modelrepository.authentication.UsernamePassword; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; + +import com.archimatetool.editor.actions.AbstractModelAction; + +import git_executor.GitExecutionException; +import git_executor.GitExecutionResult; +import git_executor.GitExecutor; +import git_executor.GitExecutor.PullMode; + +/** + * ShellArchiRepository challenges ArchiRepository with alternative GIT + * back-end. + * + * Hexagonal force field: driven by: descendants of {@link AbstractModelAction}, + * driver: git-executor + */ +public class ShellArchiRepository { + + public static enum PullOutcome { + ALREADY_UP_TO_DATE, PULLED_SUCCESSFULLY, PULL_INCOMPLETE + } + + private GitExecutor executor; + + public ShellArchiRepository() { + // inject manually as this isn't managed instance + BundleContext bundleContext = FrameworkUtil.getBundle(getClass()).getBundleContext(); + this.executor = bundleContext.getService(bundleContext.getServiceReference(GitExecutor.class)); + this.executor.setGitExecutable(new File("/snap/eclipse-pde/current/usr/bin/git")); + } + + public void setLocalRepoFolder(File localRepoFolder) { + this.executor.setGitRepo(localRepoFolder); + } + + public PullOutcome pullFromRemote(UsernamePassword npw) throws IOException { + try { + GitExecutionResult result = executor.pull(PullMode.REBASE_MERGE); + switch (result.exitCode()) { + case 0: + if (result.outputText().endsWith(".")) + return PullOutcome.ALREADY_UP_TO_DATE; + else + return PullOutcome.PULLED_SUCCESSFULLY; + default: + return PullOutcome.PULL_INCOMPLETE; + } + } catch (GitExecutionException e) { + throw new IOException(e); + } + } + + public boolean hasChanges() throws IOException { + try { + return executor.hasChanges(); + } catch (GitExecutionException e) { + throw new IOException(e); + } + } + + public boolean commit(String commitMessage, boolean amend) throws IOException { + try { + return 0 == executor.commit(commitMessage, amend, false, true).exitCode(); + } catch (GitExecutionException e) { + throw new IOException(e); + } + } + +} diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/preferences/ModelRepositoryPreferencePage.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/preferences/ModelRepositoryPreferencePage.java index 35252f1..349d15e 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/preferences/ModelRepositoryPreferencePage.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/preferences/ModelRepositoryPreferencePage.java @@ -29,7 +29,6 @@ import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Control; import org.eclipse.swt.widgets.DirectoryDialog; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.FileDialog; import org.eclipse.swt.widgets.Group; import org.eclipse.swt.widgets.Label; @@ -326,7 +325,7 @@ public void widgetSelected(SelectionEvent e) { } private String chooseIdentityFile() { - FileDialog dialog = new FileDialog(Display.getCurrent().getActiveShell()); + FileDialog dialog = new FileDialog(getShell()); dialog.setText(Messages.ModelRepositoryPreferencePage_20); // dialog.setMessage(Messages.ModelRepositoryPreferencePage_21); File file = new File(fSSHIdentityFileTextField.getText()); @@ -336,7 +335,7 @@ private String chooseIdentityFile() { } private String chooseFolderPath() { - DirectoryDialog dialog = new DirectoryDialog(Display.getCurrent().getActiveShell()); + DirectoryDialog dialog = new DirectoryDialog(getShell()); dialog.setText(Messages.ModelRepositoryPreferencePage_17); dialog.setMessage(Messages.ModelRepositoryPreferencePage_18); File file = new File(fUserRepoFolderTextField.getText()); @@ -502,6 +501,8 @@ protected void performDefaults() { updateIdentityControls(); updateProxyControls(); + + super.performDefaults(); } diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/propertysections/AuthSection.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/propertysections/AuthSection.java index 860e3ef..2386dc2 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/propertysections/AuthSection.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/propertysections/AuthSection.java @@ -23,7 +23,6 @@ import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Group; import org.eclipse.ui.dialogs.PreferencesUtil; @@ -159,7 +158,7 @@ private void storePassword(char[] password) { private void showError(Exception ex) { ex.printStackTrace(); - MessageDialog.openError(Display.getCurrent().getActiveShell(), + MessageDialog.openError(getPart().getSite().getShell(), Messages.AuthSection_11, Messages.AuthSection_12 + " " + //$NON-NLS-1$ diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryTableViewer.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryTableViewer.java index d78a761..f6066ec 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryTableViewer.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryTableViewer.java @@ -5,7 +5,9 @@ */ package org.archicontribs.modelrepository.views.history; +import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.text.DateFormat; import java.util.ArrayList; import java.util.Date; @@ -14,6 +16,7 @@ import org.archicontribs.modelrepository.IModelRepositoryImages; import org.archicontribs.modelrepository.grafico.BranchInfo; import org.archicontribs.modelrepository.grafico.BranchStatus; +import org.archicontribs.modelrepository.grafico.GraficoFileConventions; import org.archicontribs.modelrepository.grafico.IArchiRepository; import org.eclipse.jface.layout.TableColumnLayout; import org.eclipse.jface.viewers.CellLabelProvider; @@ -30,12 +33,15 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.treewalk.filter.PathFilter; import org.eclipse.swt.SWT; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.widgets.Composite; import org.eclipse.swt.widgets.Display; import com.archimatetool.editor.ui.UIUtils; +import com.archimatetool.model.IArchimateModelObject; +import com.archimatetool.model.IFolder; /** @@ -119,6 +125,15 @@ public void doSetInput(IArchiRepository archiRepo) { // setSelection(new StructuredSelection(element), true); //} } + + private static record HistoryInput(IArchiRepository repo, IArchimateModelObject obj) {} + + public void doSetInput(IArchiRepository selectedRepository, Object selected) { + if (selected instanceof IArchimateModelObject) + setInput(new HistoryInput(selectedRepository, (IArchimateModelObject)selected)); + else + doSetInput(selectedRepository); + } public void setSelectedBranch(BranchInfo branchInfo) { if(branchInfo != null && branchInfo.equals(fSelectedBranch)) { @@ -155,27 +170,47 @@ List getCommits(Object parent) { fLocalCommit = null; fOriginCommit = null; - if(!(parent instanceof IArchiRepository) || fSelectedBranch == null) { + IArchiRepository repo = null; + File elemFile = null; + + if (parent instanceof HistoryInput && ((HistoryInput) parent).obj().eContainer() instanceof IFolder) { + HistoryInput input = (HistoryInput) parent; + repo = input.repo(); + IFolder folder = (IFolder) input.obj().eContainer(); + elemFile = GraficoFileConventions.forElement( + new File(repo.getLocalRepositoryFolder(), "model"), + folder, + input.obj()); + } else if (parent instanceof IArchiRepository) + repo = (IArchiRepository) parent; + + if(fSelectedBranch == null) { return commits; } - IArchiRepository repo = (IArchiRepository)parent; - // Local Repo was deleted - if(!repo.getLocalRepositoryFolder().exists()) { + if(repo == null || !repo.getLocalRepositoryFolder().exists()) { return commits; } try(Repository repository = Git.open(repo.getLocalRepositoryFolder()).getRepository()) { // a RevWalk allows to walk over commits based on some filtering that is defined try(RevWalk revWalk = new RevWalk(repository)) { + if (elemFile != null) { + String elemPath = Path.of(repo.getLocalRepositoryFolder().getAbsolutePath()) + .relativize( + Path.of(elemFile.getAbsolutePath()) + ).toString(); + revWalk.setTreeFilter(PathFilter.create(elemPath)); + } + // Find the local branch ObjectId objectID = repository.resolve(fSelectedBranch.getLocalBranchNameFor()); if(objectID != null) { fLocalCommit = revWalk.parseCommit(objectID); revWalk.markStart(fLocalCommit); } - + // Find the remote branch objectID = repository.resolve(fSelectedBranch.getRemoteBranchNameFor()); if(objectID != null) { diff --git a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryView.java b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryView.java index 20856b2..dfda1d9 100644 --- a/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryView.java +++ b/org.archicontribs.modelrepository/src/org/archicontribs/modelrepository/views/history/HistoryView.java @@ -5,6 +5,7 @@ */ package org.archicontribs.modelrepository.views.history; +import org.archicontribs.modelrepository.IModelRepositoryImages; import org.archicontribs.modelrepository.ModelRepositoryPlugin; import org.archicontribs.modelrepository.actions.ExtractModelFromCommitAction; import org.archicontribs.modelrepository.actions.ResetToRemoteCommitAction; @@ -19,6 +20,7 @@ import org.eclipse.help.HelpSystem; import org.eclipse.help.IContext; import org.eclipse.help.IContextProvider; +import org.eclipse.jface.action.Action; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; @@ -45,7 +47,9 @@ import org.eclipse.ui.part.IContributedContentsView; import org.eclipse.ui.part.ViewPart; +import com.archimatetool.editor.ui.ArchiLabelProvider; import com.archimatetool.model.IArchimateModel; +import com.archimatetool.model.IArchimateModelObject; /** @@ -73,12 +77,14 @@ public class HistoryView private RestoreCommitAction fActionRestoreCommit; private UndoLastCommitAction fActionUndoLastCommit; private ResetToRemoteCommitAction fActionResetToRemoteCommit; - + private Action fActionToggleObjectFilter; /* - * Selected repository + * Selected repository, model-object and filtering toggle */ private IArchiRepository fSelectedRepository; + private IArchimateModelObject fSelectedModelObject; + private boolean fModelObjectFiltered = false; @Override @@ -195,9 +201,7 @@ private void makeActions() { fActionResetToRemoteCommit = new ResetToRemoteCommitAction(getViewSite().getWorkbenchWindow()); fActionResetToRemoteCommit.setEnabled(false); - // Register the Keybinding for actions -// IHandlerService service = (IHandlerService)getViewSite().getService(IHandlerService.class); -// service.activateHandler(fActionRefresh.getActionDefinitionId(), new ActionHandler(fActionRefresh)); + fActionToggleObjectFilter = new ToggleObjectFilter("Link Selected Object", Action.AS_CHECK_BOX); } /** @@ -219,23 +223,6 @@ public void menuAboutToShow(IMenuManager manager) { getSite().registerContextMenu(menuMgr, getHistoryViewer()); } - - /** - * Make Any Local Bar Menu Actions - */ -// protected void makeLocalMenuActions() { -// IActionBars actionBars = getViewSite().getActionBars(); -// -// // Local menu items go here -// IMenuManager manager = actionBars.getMenuManager(); -// manager.add(new Action("&View Management...") { -// public void run() { -// MessageDialog.openInformation(getViewSite().getShell(), -// "View Management", -// "This is a placeholder for the View Management Dialog"); -// } -// }); -// } /** * Make Local Toolbar items @@ -251,8 +238,9 @@ protected void makeLocalToolBarActions() { manager.add(new Separator()); manager.add(fActionUndoLastCommit); manager.add(fActionResetToRemoteCommit); - manager.add(new Separator()); + manager.add(fActionToggleObjectFilter); + manager.add(new Separator()); } /** @@ -309,39 +297,39 @@ public void setFocus() { } @Override - public void selectionChanged(IWorkbenchPart part, ISelection selection) { - if(part == null || part == this || selection == null) { - return; - } - - Object selected = ((IStructuredSelection)selection).getFirstElement(); + public void selectionChanged(IWorkbenchPart iPart, ISelection iSelection) { + + if (iPart == null || iSelection == null) + return; + if (iPart == this) + return; + IArchiRepository selectedRepository = null; + IArchimateModelObject selectedObject = null; + Object selected = ((IStructuredSelection)iSelection).getFirstElement(); + // Repository selected if(selected instanceof IArchiRepository) { selectedRepository = (IArchiRepository)selected; - } + } // Model selected, but is it in a git repo? else { - IArchimateModel model = part.getAdapter(IArchimateModel.class); + IArchimateModel model = iPart.getAdapter(IArchimateModel.class); if(GraficoUtils.isModelInLocalRepository(model)) { selectedRepository = new ArchiRepository(GraficoUtils.getLocalRepositoryFolderForModel(model)); } + + if (selected != null && selected instanceof IArchimateModelObject) + selectedObject = (IArchimateModelObject) selected; } - // Update if selectedRepository is different - if(selectedRepository != null && !selectedRepository.equals(fSelectedRepository)) { - // Store last selected - fSelectedRepository = selectedRepository; - - // Set label text - fRepoLabel.setText(Messages.HistoryView_0 + " " + selectedRepository.getName()); //$NON-NLS-1$ - - // Set History first - getHistoryViewer().doSetInput(selectedRepository); - - // Set Branches + + if (selectedRepository != null && selectedRepository != fSelectedRepository) { + fSelectedRepository = selectedRepository; + + // Set Branches getBranchesViewer().doSetInput(selectedRepository); // Update actions @@ -350,25 +338,51 @@ public void selectionChanged(IWorkbenchPart part, ISelection selection) { fActionUndoLastCommit.setRepository(selectedRepository); fActionResetToRemoteCommit.setRepository(selectedRepository); } + + if (selectedObject != null && selectedObject != fSelectedModelObject) + fSelectedModelObject = selectedObject; + + if (fSelectedRepository != null) // no distinct repo selected yet + setSelectedRepoAndObject(); } - @Override + private void setSelectedRepoAndObject() { + if (fModelObjectFiltered) + getHistoryViewer().doSetInput(fSelectedRepository, fSelectedModelObject); + else + getHistoryViewer().doSetInput(fSelectedRepository); + updateLabel(); + } + + private void updateLabel() { + String objectLabel = ArchiLabelProvider.INSTANCE.getLabelNormalised(fSelectedModelObject); + + String label = Messages.HistoryView_0 + + " " + fSelectedRepository.getName(); + + if (fModelObjectFiltered && objectLabel.length() > 0) + label += " (" + objectLabel+ ")"; //$NON-NLS-1$ + + fRepoLabel.setText(label); + } + + @Override public void repositoryChanged(String eventName, IArchiRepository repository) { if(repository.equals(fSelectedRepository)) { switch(eventName) { case IRepositoryListener.HISTORY_CHANGED: - fRepoLabel.setText(Messages.HistoryView_0 + " " + repository.getName()); //$NON-NLS-1$ + updateLabel(); getHistoryViewer().setInput(repository); break; case IRepositoryListener.REPOSITORY_DELETED: - fRepoLabel.setText(Messages.HistoryView_0); - getHistoryViewer().setInput(""); //$NON-NLS-1$ + updateLabel(); + getHistoryViewer().setInput(""); //$NON-NLS-1$ fSelectedRepository = null; // Reset this break; case IRepositoryListener.REPOSITORY_CHANGED: - fRepoLabel.setText(Messages.HistoryView_0 + " " + repository.getName()); //$NON-NLS-1$ + updateLabel(); break; case IRepositoryListener.BRANCHES_CHANGED: @@ -415,4 +429,18 @@ public IContext getContext(Object target) { public String getSearchExpression(Object target) { return Messages.HistoryView_1; } + + private final class ToggleObjectFilter extends Action { + private ToggleObjectFilter(String text, int style) { + super(text, style); + super.setImageDescriptor(IModelRepositoryImages.ImageFactory.getImageDescriptor(IModelRepositoryImages.ICON_SYNCED)); + } + + @Override + public void run() { + fModelObjectFiltered = this.isChecked(); + setSelectedRepoAndObject(); + } + } + }