Bug 569495 - JGit allows Push to update checked out branch (receive.denyCurrentBranch and receive.denyDeleteCurrent not implemented)
Summary: JGit allows Push to update checked out branch (receive.denyCurrentBranch and ...
Status: NEW
Alias: None
Product: JGit
Classification: Technology
Component: JGit (show other bugs)
Version: unspecified   Edit
Hardware: PC Windows 10
: P3 normal (vote)
Target Milestone: ---   Edit
Assignee: Project Inbox CLA
QA Contact:
URL:
Whiteboard:
Keywords: helpwanted
Depends on:
Blocks:
 
Reported: 2020-12-05 11:39 EST by Maxim Shclover CLA
Modified: 2020-12-07 06:33 EST (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Maxim Shclover CLA 2020-12-05 11:39:17 EST
When I try to PUSH into checked out branch on remote I am getting an error with GIT BASH and success when using JGIT. As a result I end up with successful PUSH (I can see commit ) and old version of the branch being staged... How do I fix that. I want JGIT to fail while updating checked out branch. The code is very straightforward: git.push().setCredentialsProvider(cp).call();
Comment 1 Thomas Wolf CLA 2020-12-05 11:47:12 EST
Sorry, I don't quite understand your description.

Please show a fully working example. (Use two local repositories and the file:// protocol instead of a real remote and https/ssh. Or use a public repo at Github as remote. Show how you clone, how you reset to an older state, and then how you push with command-line git and with JGit.)

For the JGit part please include a fully working code sample.
Comment 2 Maxim Shclover CLA 2020-12-06 12:55:07 EST
I do the following in GIT BASH
1.Create local repo "a" with one file and commit it (only master branch);
2.Make a local clone "b" ( git clone a b ) and change the file there and create another commit.
3.Now when I do push ( git push ) I get an error:
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote:
remote: You can set the 'receive.denyCurrentBranch' configuration variable
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote:
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.

If instead of doing push in GIT BASH I use my java program I get success.
In my program I get git repo and then call

Git git = getGit( getGitWorkDir() );
Iterable<PushResult> resultIterable = git.push().setCredentialsProvider(cp).call();

public static Git getGit ( File gitWorkDir ) throws Exception
    {
        try 
        {
            Git git = Git.open(gitWorkDir);
            return git;
        } 
        catch (Exception e) 
        {    
            return null;
        }
    } 
public File getGitWorkDir()
    {
        FileRepositoryBuilder repositoryBuilder = new FileRepositoryBuilder();
        File gitStartDir = new File("c:/temp/b");
        repositoryBuilder.findGitDir( gitStartDir );
        File gitWorkDir = repositoryBuilder.getGitDir();
        
        return gitWorkDir;
    }

Hope it helps.
Comment 3 Thomas Wolf CLA 2020-12-06 13:34:25 EST
Thanks, that helps. JGit does not yet implement all the receive.* git configs. In particular it does not implement receive.denyCurrentBranch and receive.denyDeleteCurrent.
Comment 4 Maxim Shclover CLA 2020-12-06 20:17:02 EST
Any plans to address this issue? How can I get current checked out remote branch with JGit?
Comment 5 Thomas Wolf CLA 2020-12-07 06:33:58 EST
(In reply to Maxim Shclover from comment #4)
> Any plans to address this issue?

None in particular. Like most open-source projects JGit is maintained and developed by volunteers; they'll do whatever they feel like doing. They mostly are interested in fixing or improving things that affect them, too.

receive.denyCurrentBranch has only an effect for non-bare repositories. Git servers typically only host bare repositories. So it won't occur with Gerrit, and thus the Google people who are contributing to JGit are unlikely to pick this up. In practice, it'll occur only with the file:// protocol, and there's apparently not many people using that. So it's not very likely that some other regular contributor is going to invest time on this. Personally, I have several other irons in the fire right now. I might eventually pick it up, but don't hold your breath.

> How can I get current checked out remote branch with JGit?

You could use LsRemoteCommand to get the remote HEAD, which is either a symref to the branch, or a SHA1. In the latter case, you could get the SHA1s of the other refs/heads/ refs and look at ones that point to the same SHA1. Though that is a bit imprecise if there are several remote branches pointing to the HEAD commit. Compare https://git.eclipse.org/r/c/jgit/jgit/+/171875 .

But maybe you're interested in fixing this yourself in JGit directly? It needs to be implemented in ReceivePack. Starting point would be the ReceiveConfig, and then probably adapting validateCommands(), then writing new tests and probably adapting existing tests. After a quick glance, it doesn't look too difficult to do this; just an unknown amount of work (I suspect mostly with tests).

Interested? We sure could use some helping hands :-) See [1] for how to set up an Eclipse to work on EGit/JGit, and [2] for actually contributing.

[1] https://wiki.eclipse.org/EGit/Contributor_Guide#Automated_Developer_Setup
[2] https://wiki.eclipse.org/EGit/Contributor_Guide#Contributing_Patches