Skip to content
This repository has been archived by the owner on Apr 14, 2020. It is now read-only.

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
bsideup committed Sep 19, 2013
1 parent 958e12a commit 2fb0574
Show file tree
Hide file tree
Showing 9 changed files with 397 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.idea/
.DS_Store
/out
IDEA-GitLab-Integration.jar
15 changes: 15 additions & 0 deletions IDEA-GitLab-Integration.iml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="PLUGIN_MODULE" version="4">
<component name="DevKit.ModuleBuildProperties" url="file://$MODULE_DIR$/META-INF/plugin.xml" />
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/resources" isTestSource="false" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" scope="PROVIDED" name="git4idea" level="application" />
</component>
</module>

44 changes: 44 additions & 0 deletions META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<idea-plugin version="2">
<id>ru.trylogic.idea.gitlab.integration</id>
<name>GitLab integration</name>
<version>1.0</version>
<vendor email="bsideup@gmail.com" url="https://github.com/bsideup">Sergei Egorov</vendor>

<description><![CDATA[
<a href="http://gitlab.org/">GitLab</a> integration plugin.
Support "Open file in browser" command.
]]></description>

<change-notes><![CDATA[
Initial release. "Open file in browser" command.
]]>
</change-notes>

<idea-version since-build="107.105"/>

<depends>com.intellij.modules.vcs</depends>
<depends>com.intellij.modules.lang</depends>
<depends>Git4Idea</depends>

<application-components>
</application-components>

<project-components>
</project-components>

<actions>
<action id="GitLab.Open.In.Browser"
class="ru.trylogic.idea.gitlab.integration.actions.GitLabOpenInBrowserAction">
<add-to-group group-id="EditorPopupMenu"/>
<add-to-group group-id="ProjectViewPopupMenu"/>
<add-to-group group-id="EditorTabPopupMenu"/>
</action>

<!--action id="GitLab.Open.Commit.In.Browser" class="ru.trylogic.idea.gitlab.integration.actions.GitLabShowCommitInBrowserFromLogAction">
<add-to-group group-id="Git.LogContextMenu" />
</action-->
</actions>

<extensions defaultExtensionNs="com.intellij">
</extensions>
</idea-plugin>
Binary file added resources/ru/trylogic/idea/gitlab/gitlab_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
17 changes: 17 additions & 0 deletions src/icons/GitlabIcons.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package icons;

import com.intellij.openapi.util.IconLoader;

import javax.swing.*;

/**
* NOTE THIS FILE IS AUTO-GENERATED by the build/scripts/icons.gant
* Don't repeat mistakes of others ;-)
*/
public class GitlabIcons {
private static Icon load(String path) {
return IconLoader.getIcon(path, GitlabIcons.class);
}

public static final Icon Gitlab_icon = load("/ru/trylogic/idea/gitlab/gitlab_icon.png"); // 16x16
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package ru.trylogic.idea.gitlab.integration.actions;

import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import git4idea.repo.GitRepository;
import icons.GitlabIcons;
import ru.trylogic.idea.gitlab.integration.utils.GitlabUrlUtil;

abstract class AbstractGitLabShowCommitInBrowserAction extends DumbAwareAction {

public AbstractGitLabShowCommitInBrowserAction() {
super("Open on GitLab", "Open the selected commit in browser", GitlabIcons.Gitlab_icon);
}

protected static void openInBrowser(GitRepository repository, String revisionHash) {

String remote = GitlabUrlUtil.findRemoteUrl(repository);
final String repoUrl = GitlabUrlUtil.makeRepoUrlFromRemoteUrl(remote);

String url = repoUrl + "/commit/" + revisionHash;
BrowserUtil.launchBrowser(url);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
package ru.trylogic.idea.gitlab.integration.actions;

import com.intellij.ide.BrowserUtil;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.project.DumbAwareAction;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vcs.changes.ChangeListManager;
import com.intellij.openapi.vfs.VirtualFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import git4idea.GitLocalBranch;
import git4idea.GitRemoteBranch;
import git4idea.GitUtil;
import git4idea.repo.GitRepository;
import git4idea.repo.GitRepositoryManager;
import ru.trylogic.idea.gitlab.integration.utils.GitlabUrlUtil;
import icons.GitlabIcons;

public class GitLabOpenInBrowserAction extends DumbAwareAction {

public static final String CANNOT_OPEN_IN_BROWSER = "Cannot open in browser";

static void setVisibleEnabled(AnActionEvent e, boolean visible, boolean enabled) {
e.getPresentation().setVisible(visible);
e.getPresentation().setEnabled(enabled);
}

protected GitLabOpenInBrowserAction() {
super("Open on GitLab", "Open corresponding link in browser", GitlabIcons.Gitlab_icon);
}

@Override
public void update(final AnActionEvent e) {
Project project = e.getData(PlatformDataKeys.PROJECT);
VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
if (project == null || project.isDefault() || virtualFile == null) {
setVisibleEnabled(e, false, false);
return;
}
GitRepositoryManager manager = GitUtil.getRepositoryManager(project);

final GitRepository gitRepository = manager.getRepositoryForFile(virtualFile);
if (gitRepository == null) {
setVisibleEnabled(e, false, false);
return;
}

ChangeListManager changeListManager = ChangeListManager.getInstance(project);
if (changeListManager.isUnversioned(virtualFile)) {
setVisibleEnabled(e, true, false);
return;
}

Change change = changeListManager.getChange(virtualFile);
if (change != null && change.getType() == Change.Type.NEW) {
setVisibleEnabled(e, true, false);
return;
}

setVisibleEnabled(e, true, true);
}

@Override
public void actionPerformed(final AnActionEvent e) {
final Project project = e.getData(PlatformDataKeys.PROJECT);
final VirtualFile virtualFile = e.getData(PlatformDataKeys.VIRTUAL_FILE);
final Editor editor = e.getData(PlatformDataKeys.EDITOR);
if (virtualFile == null || project == null || project.isDisposed()) {
return;
}

String urlToOpen = getUrl(project, virtualFile, editor);
if (urlToOpen != null) {
BrowserUtil.launchBrowser(urlToOpen);
}
}

@Nullable
public static String getUrl(@NotNull Project project, @NotNull VirtualFile virtualFile, @Nullable Editor editor) {

GitRepositoryManager manager = GitUtil.getRepositoryManager(project);
final GitRepository repository = manager.getRepositoryForFile(virtualFile);
if (repository == null) {
StringBuilder details = new StringBuilder("file: " + virtualFile.getPresentableUrl() + "; Git repositories: ");
for (GitRepository repo : manager.getRepositories()) {
details.append(repo.getPresentableUrl()).append("; ");
}
showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find git repository", details.toString());
return null;
}

final String remoteUrl = GitlabUrlUtil.findRemoteUrl(repository);
if (remoteUrl == null) {
showError(project, CANNOT_OPEN_IN_BROWSER, "Can't find gitlab remote");
return null;
}

final String rootPath = repository.getRoot().getPath();
final String path = virtualFile.getPath();
if (!path.startsWith(rootPath)) {
showError(project, CANNOT_OPEN_IN_BROWSER, "File is not under repository root", "Root: " + rootPath + ", file: " + path);
return null;
}

String branch = getBranchNameOnRemote(project, repository);
if (branch == null) {
return null;
}

String relativePath = path.substring(rootPath.length());
String urlToOpen = makeUrlToOpen(editor, relativePath, branch, remoteUrl);
if (urlToOpen == null) {
showError(project, CANNOT_OPEN_IN_BROWSER, "Can't create properly url", remoteUrl);
return null;
}

return urlToOpen;
}

private static void showError(Project project, String cannotOpenInBrowser) {
showError(project, cannotOpenInBrowser, null);
}

private static void showError(Project project, String cannotOpenInBrowser, String s) {
showError(project, cannotOpenInBrowser, s, null);
}

private static void showError(Project project, String cannotOpenInBrowser, String s, String s1) {
System.out.println(cannotOpenInBrowser + ";" + s + ";" + s1);
}

@Nullable
private static String makeUrlToOpen(@Nullable Editor editor,
@NotNull String relativePath,
@NotNull String branch,
@NotNull String remoteUrl) {
final StringBuilder builder = new StringBuilder();
final String repoUrl = GitlabUrlUtil.makeRepoUrlFromRemoteUrl(remoteUrl);
if (repoUrl == null) {
return null;
}
builder.append(repoUrl).append("/blob/").append(branch).append(relativePath);

if (editor != null && editor.getDocument().getLineCount() >= 1) {
// lines are counted internally from 0, but from 1 on gitlab
SelectionModel selectionModel = editor.getSelectionModel();
final int begin = editor.getDocument().getLineNumber(selectionModel.getSelectionStart()) + 1;
final int selectionEnd = selectionModel.getSelectionEnd();
int end = editor.getDocument().getLineNumber(selectionEnd) + 1;
if (editor.getDocument().getLineStartOffset(end - 1) == selectionEnd) {
end -= 1;
}
builder.append("#L").append(begin).append('-').append(end);
}

return builder.toString();
}

@Nullable
public static String getBranchNameOnRemote(@NotNull Project project, @NotNull GitRepository repository) {
GitLocalBranch currentBranch = repository.getCurrentBranch();
if (currentBranch == null) {
showError(project, CANNOT_OPEN_IN_BROWSER,
"Can't open the file on GitLab when repository is on detached HEAD. Please checkout a branch.");
return null;
}

GitRemoteBranch tracked = currentBranch.findTrackedBranch(repository);
if (tracked == null) {
showError(project, CANNOT_OPEN_IN_BROWSER, "Can't open the file on GitLab when current branch doesn't have a tracked branch.",
"Current branch: " + currentBranch + ", tracked info: " + repository.getBranchTrackInfos());
return null;
}

return tracked.getNameForRemoteOperations();
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package ru.trylogic.idea.gitlab.integration.actions;


import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitUtil;
import git4idea.GitVcs;
import git4idea.history.browser.GitCommit;
import git4idea.repo.GitRepository;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

public class GitLabShowCommitInBrowserFromLogAction extends AbstractGitLabShowCommitInBrowserAction {

@Nullable
private static EventData collectData(AnActionEvent e) {
Project project = e.getData(PlatformDataKeys.PROJECT);
if (project == null || project.isDefault()) {
return null;
}

GitCommit commit = e.getData(GitVcs.GIT_COMMIT);
if (commit == null) {
return null;
}

VirtualFile root = commit.getRoot();
GitRepository repository = GitUtil.getRepositoryManager(project).getRepositoryForRoot(root);
if (repository == null) {
return null;
}

return new EventData(repository, commit);
}

@Override
public void update(AnActionEvent e) {
EventData eventData = collectData(e);
e.getPresentation().setVisible(eventData != null);
e.getPresentation().setEnabled(eventData != null);
}

@Override
public void actionPerformed(AnActionEvent e) {
EventData eventData = collectData(e);
if (eventData != null) {
openInBrowser(eventData.getRepository(), eventData.getCommit().getHash().getValue());
}
}

private static class EventData {
@NotNull
private final GitRepository myRepository;
@NotNull
private final GitCommit myCommit;

private EventData(@NotNull GitRepository repository, @NotNull GitCommit commit) {
myRepository = repository;
myCommit = commit;
}

@NotNull
public GitRepository getRepository() {
return myRepository;
}

@NotNull
public GitCommit getCommit() {
return myCommit;
}
}

}
Loading

0 comments on commit 2fb0574

Please sign in to comment.