Get project' git repositories in a project component
Hi,
I'm working on a plugin who need to detect if a git repository corresponding to a special remote is enabled. So I created my detetor, I created my Project Component (https://gist.github.com/Kendos-Kenlen/0c5ef1c75e31c1e856b6), but when I try to detect repositories, no repositories exist in the GitRepositoryManager (the following code print an empty array :
public CleverIdeaProjectComponent(Project project, GitRepositoryManager gitRepositoryManager, GitProjectDetector gitProjectDetector) {
myProject = project;
myGitRepositoryManager = gitRepositoryManager;
myGitProjectDetector = gitProjectDetector;
System.out.println(gitRepositoryManager.getRepositories());
}
The problem doesn't happen if I start the detection with an action, so I suppose that the list of repositories is just not loaded. So, how can I resolve this issue ? My idea is to check git repositories at project starting to know if an application is linked with our service.
Another question : why some servcies are declared with :<projectService serviceInterface="" serviceImplementation=""/>
and some other with :
<projectService serviceImplementation=""/>
Which one is better/correct and what's the difference if the Interface and the Implementation are the same ?
Please sign in to leave a comment.
You're right. If you look into the VcsRepositoryManager (the actual container of this information) you'll see that the repositories are updated after directoryMappingsChange, which at first happens when the ProjectLevelVcsManager's mappings are initialized.
In IDEA source code we use ProjectLevelVcsManagerImpl.addInitializationRequest to make sure our components are initialized after the mappings do (VcsInitObject#MAPPINGS). The VcsInitObject is a enum, so currently there is no way to pass your own request there, but you can try using one of the existing ones:
The GitRepositoryManager doesn't use this VcsInitObject technique for now (so it is not defined when it will be updated initially or after mappings change), but GitRepositoryManager#getRepositoryForRoot will cause the collection of repositories to be updated automatically if needed.
There is no difference if the interface and implementation are the same: the second notation is just a shorthand.
Hi,
Thank you for your help, I successfuly implemented the project component.gges
I suggest to document the way IntelliJ use to load part like the VCS système (because I suppose that it's not the only thing who works like that), the event system and other things related.
I didn't find documentation about it in the SDK doc, but I think that it's useful for developpers. I already created an issue about VCS documentation here : https://youtrack.jetbrains.com/issue/IJSDK-61 but I think that VCS isn't the only part of the IDE covered by this loading process.
Edit : How can I run a Git Push ? I want to create a button to easily deploy the last commit on our service, but I don't really know what should I do. I found the "GitPushOperation" class but I'm not sure how to use it, especially for the 3rd parameter :
Unfortunately most of the functionality which you've mentioned (including most of Git support, and including the VcsInitObject stuff which we've discussed above - as you might have noticed, it is not API) has no official API, that's why it is not documented. However, we're working on this problem and plan both to extract API for most useful parts of the functionality, and to document it properly.
To push don't call GitPushOperation directly. Instead use GitPushSupport.getPusher.push(). For example, like this:
Hi,

Okay, I understand now why there is not an "easy" way to play with Git and the VCS system. I suppose that providing an API will be a good thing for plugins like Settings Repository. I looked the source code for my plugin, and it use JGit instead of the IntelliJ git plugin, is not really "logic", since intelliJ provide the necessary to manage Git.
If I can make a comment about IntelliJ platform, is that I find it quite "messy". I spend a lot of time watching how IntelliJ words for my plugin, and because it interests me, and I must say that I do not find the answer easily.
IntelliJ is well built, it is not the concern (and it's definitly my prefered IDE since 2 years now :D). We can do a lot of things when creating a plugin and it is a very rich IDE and platform, but it is very poorly documented (a big part of the code lack of documentation). Only the Open API is documented so it take long hours to find how to do a simple thing that isn't documented in the SDK doc.
More documentation would be definitely a plus. I would like to contribute to the platform to add features that I would like to see implemented, or improve what I can, but it is currently almost impossible because it is really hard to navigate and it miss from a lot of documentation.
I tried some month ago to solve this issue (that I created) : https://youtrack.jetbrains.com/issue/CPP-1374 but I failed because of this lack of documentation. IntelliJ architecture (folder structures) is not necessarily obvious in the begriming and find what you want is hard (what is the difference between ***-api and ***-impl? Which class sould I use ? What is this folder for ?...). I created a very little pull request the other day (https://github.com/JetBrains/intellij-community/pull/293) because I was searching a function, and no JavaDoc was available so I had to go in the source code, etc ... bref, I lost time with a simple thing (while it takes two lines of doc) and it happen often, so I wrote two lines of doc to help people after me (and to use the Quick Doc :D ).
I sincerely hope you will document more code, it would please me a lot to be able to put my hands in the code, it's very interesting for me as a student, I learn a lot in Java. And two lines of code take only few seconds to be written, but help to save many hours of searching ! ;) So please, provide more JavaDoc and SDK Doc !
________________________
Btw, I tried the code you gave me, but it can't works because GitPushSource is an abstract class and is not public, so I can't access it in my plugin.
Honestly, I have no idea why does it use JGit. I will ask the author. My assumption is: it is so to avoid Git installation requirement: there could be a lot of users of the Settings Repository which don't use Git at all.
Well, this one is simple. You should use classes from "-api" modules, but not from "-impl". The api-modules form the API, which means that in general they provide more clean and understandable interfaces with javadocs and, which is even more important, which are changes with much more care to avoid breaking of 3-party plugins. On the other hand, the impl-modules can rapidly and heavily change, and nothing is guaranteed here.
Of course, sometimes you don't find the API you need for you task: in this case the right thing to do is to request the necessary API from the IntelliJ IDEA team, and use classes from impl on our own risk until that API is created.
Sending such a documention pull request is a very good move, let me say. Will be accepted shortly.
The problem is not that it is abstract, but because it is not public.
But the solution is simple: just use PushSource instead of GitPushSource:
Hi,
Honestly, I have no idea why does it use JGit. I will ask the author. My assumption is: it is so to avoid Git installation requirement: there could be a lot of users of the Settings Repository which don't use Git at all.
I thought to this reason too, but considering that there is not an API available for Git (or others VCS), I suppose it was just more convenient. As you explained, it's not easy to play with Git for the moment so I suppose it was the easiest way.
Well, this one is simple. You should use classes from "-api" modules, but not from "-impl". The api-modules form the API, which means that in general they provide more clean and understandable interfaces with javadocs and, which is even more important, which are changes with much more care to avoid breaking of 3-party plugins. On the other hand, the impl-modules can rapidly and heavily change, and nothing is guaranteed here.
Of course, sometimes you don't find the API you need for you task: in this case the right thing to do is to request the necessary API from the IntelliJ IDEA team, and use classes from impl on our own risk until that API is created.
Thank you for the explaination. it was an example, but it clarify what I thought. I didn't had problem with missing API except for git but if I need an API, I'll ask it on youtrack then ! And I follow the evolution of the platform with EAP so I can adjust my code if a change is made. EAP are cool for that !
I'll continue to document code if I find undocumented method that I can complete (and try to create bigger pull requests :p). This is the only thing that I do to help for the moment.
Alternatively, you may implement the PushSource on your own. Or (which is a dirty but common way to overcome the package-visibility problem), you can make a public wrapper (or descendant) of the GitPushSource and place it into the git4idea.push package. But better stick with the PushSource since you don't need to access GitPushSource directly anyway.
I tried to use PushSource, but pushSupport.getPusher().push() is problematic : it take as first parameter a Map<GitRepository, PushSpec<GitPushSource, GitPushTarget>>, who use GitPushSource explicitly... I tried to crate a public wrapper named GitPushSourcePub, but the push method doesn't accept it ... :(
I'm sorry if I miss a trick, I'm far from being a Java expert.
The only way I found it's to put my class directly in the package (to have git4idea.push.DeployAction) But it's really disgusting and I really appreciate to do things differently ...
Ah, I've missed this restriction.
OK, I've just made GitPushSource public, and pushed the change to the master branch on intellij-community. So you're free to use it now.
Thank you !
Hi,
I need some help to build my plugin, I can't find a good way to do what I want...
My plugin is for a service similar to Heroku. To help the developer, we decided to offer him the possibility to directly push on our service from the IDE, get logs, create new app, ...
I've created a detector that read all remotes in the project and, if I detect a remote corresponding to an application on our service, I request our API to check if the user own the application and to get info about it.
But I've a problem : to push, I need to know where to push (logic) but I don't know how I can link one of my "Applications" (who is a simple object) to the good repository ?
For example, I can have the following git configuration :
How, when I want to push, can I specity that I want to push on the clever remote, and how can I associate the "Application" to its remote and persist it ? I looked, but it's not possible to get the repository from a remote (ex remote.getRepository()).
I tried to persist a GitRepository but it's seriously a bad idea (it just doesn't work).
Why don't you just use GitRemote object? Or a pair of GitRepository and GitRemote.
When I try to persist a GitRepository or a GitRemote, it gives me that :
That's because these are custom objects that are not annotated as persistable. See com.intellij.dvcs.push.PushSettings.ForcePushTargetInfo for example of a custom persistable class.
However, in this case I'd just store 2 Strings: the path to the root + the URL of the remote (or wrap them into a custom class). Should be enough to get proper GitRepository and GitRemote objects when you need them (GitRepositoryManager.getRepositoryForRoot(), GitRepository.getRemotes() -> find by URL).
Just create a new GitPushTarget from a GitRemoteBranch, which you can either get from the list of known remote branches, either create a new one. That's exactly what is being done in GitPushSupport#makeTargetForNewBranch.
Okay, I understand. Thank you for your help !
I tried to get the GitPushSupport, but
GitPushSupport pushSupport = ServiceManager.getService(project, GitPushSupport.class);
is always null... I looked the GIt plugin but it never get from the ServiceManager.
I was wrong. The GitPushSupport is not a project service, but an implementation of the common extension point. Currently the only way to get an instance of the GitPushSupport is to traverse over all existing extension point implementations and find the one which corresponds to the VCS you have.
I've just pushed a change that adds a utility method for this task to the DvcsUtil class: com.intellij.dvcs.DvcsUtil#getPushSupport
After some works on another project, I'm back to this one with a problem.
When I launch a push operation :
... the process block while executing "pushSupport.getPusher().push()". I've looked with the debugger and found that it block here (thread).
I didn't go deeper in IntelliJ with the debugger (I tried but ... it goes too deep). The IDE freeze and I can't continue to use it, and the push operation isn't performed.
That's obviously because you're running Git from the EDT thread, thus freezing the whole UI until the operation completes. Which can take forever if Git waits for a password, and the password prompt can't be displayed - well, because the EDT is occupied.
The solution is to make the task in another thread. Use one of 3 approaches:
* ApplicationManager.getApplication().executeOnPooledThread <- to execute the task on a background thread.
* ProgressManager.getInstance().run(new Task.Backgroundable()) <- to execute the task on a background thread with a progress indicator in the status bar (most of Git commands in IDEA use this approach).
* ProgressManager.getInstance().run(new Task.Modal()) <- to execute the task with a modal progress dialog. This will not allow UI interaction (because the progress is modal), but UI woudn't freeze, and will show the password prompt. This approach is rarely needed when executing something like git push, so I'm just mentioning it to make you have the full picture.
\o/
Thank you ! I didn't thought to that. Everything work well now ! :)
Hi,
I want to create a "Check out from VC" action for my plugin, similar to the Github one. I looked in the plugin code but I didn't found what is used to perform the action (add an item to the "Check out from VC" menu, perform the cloning and open the project). Can you help me ?
And I saw that GitBranch.DUMMY_HASH is marked as deprecated. What should I use instead ?
You have to implement the `checkoutProvider` extension point: implement the CheckoutProvider interface and add the entry to your plugin.xml. Since you're going to checkout from Git, you'll probably reuse some stuff from GitCheckoutProvider and GithubCheckoutProvider (which obviously share some methods between each other).
If you know the commit which the branch is pointing to - use its hash. Otherwise you can use DUMMY_HASH. The hash is retrived from GitBranch only in few specific situations (search for GitBranch#getHash() usages), so it is safe to use arbitrary value in others.
We've marked DUMMY_HASH as deprecated, but later found out that it is not always convenient to identify the hash each time the GitBranch object is needed, so some day we'll probably remove this parameter from GitBranch at all.