What is the best way to get the branch of a file ?

Answered

Hi all,

 

I wrote following code. It executed when the editor is changing file or during a schedule timer task (every 30 seconds) 

public String getBranchOfFile(Project project, VirtualFile file) {
String branchName = null;
if(file != null) {
FilePath filePath = VcsUtil.getFilePath(file.getPath());
ProjectLevelVcsManager.getInstance(project).findVersioningVcs(file);
AbstractVcs vcsFor = VcsUtil.getVcsFor(project, filePath);
if(vcsFor != null) {
for (BranchStateProvider provider : BranchStateProvider.EP_NAME.getExtensionList(
project)) {
if (provider.getClass().getName().contains(vcsFor.getName())) {
branchName = Optional.ofNullable(provider.getCurrentBranch(filePath)).map(
BranchData::getBranchName).map(String::toLowerCase).orElse(null);
break;
}
}
}
}
return branchName;


 

I noticed that somehow during the first call the VcsUtil.getVcsFor(project, filePath) returns null (whereas the next call with the same parameter return something)

 

Second strange thing : BranchStateProvider.EP_NAME.getExtensionList returns git (wanted as I will start using that in my team), svn (wanted as it is the company official versioning tool)  and some other stuff name hg  ?

and finaly third thing : The UI seems less responsive when I change tab (and as said it will do this method). 
Therefore my question : what is the best way to get the branch of a file ? 

Maybe there is something easier and quicker like file.getcurrentBranch (but I didn't found something as easy as that :P ) ? 

 

 

0
4 comments

>ProjectLevelVcsManager.getInstance(project).findVersioningVcs(file);
You should not need to call this method.

>if (provider.getClass().getName().contains(vcsFor.getName()))
`BranchStateProvider` should handle it itself and return 'null' if the file is under another vcs.
So you can use it as `BranchStateProvider.EP_NAME.getExtensionList(project).asSequence().mapNotNull { it.getCurrentBranch(path) }.firstOrNull()`.

>I noticed that somehow during the first call the VcsUtil.getVcsFor(project, filePath) returns null
Yes, VCS roots can be initialised late during Project opening (and be changed at any time).
You can use `com.intellij.openapi.vcs.impl.ProjectLevelVcsManagerImpl#addInitializationRequest` with `VcsInitObject#AFTER_COMMON` to postpone first execution until everything is initialised.
Or listen for all changes in the mappings using `com.intellij.openapi.vcs.ProjectLevelVcsManager#VCS_CONFIGURATION_CHANGED` topic.

> Second strange thing
Could you clarify, what's strange here? This EP returns implementations for all vcs plugins, that are enabled and provide this info (so far only 3 mentioned do so).
"Hg" is a common abbreviation for https://www.mercurial-scm.org/

>The UI seems less responsive when I change tab
AFAUI, this method should be fast enough to be called from EDT (if it's not in a tight loop, of course).
There are might be some performance issue with specific repository or configuration (ex: many registered roots, many branches in repository, etc).
You can try to profile IDE to find out (so that we could fix it in EP implementation).

0

>The UI seems less responsive when I change tab
On second thought, calling "findVersioningVcs" above might be the issue here.

0

wow this is a lot more than expected :) 
thanks a lot Aleksey, i'll try the different ideas and can finally finish my work on this part :) 

 

0

concerning hg i was a bit wondered as the project has no mercurial settings at all and as I did not add dependency to it.

Indeed for git and svn I needed to explicitly add the plugins

'svn4idea', 'git4idea'
0

Please sign in to leave a comment.