LocalRegistry.jl icon indicating copy to clipboard operation
LocalRegistry.jl copied to clipboard

Automatically check out dummy branch when modifying a repo

Open jakobnissen opened this issue 3 years ago • 6 comments

When modifying a local repo, just created, I get an error. This happens because LocalRegistry.jl tries to push to the original repo, and you cannot push to the currently checked out branch of the repo.

This could be solved a number of ways. Automatically setting git config --bool core.bare true in new repositories. Or automatically create a dummy branch and switch to it when necessary.

jakobnissen avatar Aug 11 '21 11:08 jakobnissen

Can you describe more exactly what you did? I suspect it was something unintended and that the documentation might need some clarification.

GunnarFarneback avatar Aug 16 '21 09:08 GunnarFarneback

Yes, it's likely I did something wrong. Here is what I did:

I have a centralized registry called SSI in a directory /path/to/Registry. I then enter Julia and type:

(@v1.6) pkg> registry add /path/to/Registry

This then clones the current active branch of Registry into ~/.julia/registries/SSI. In my example, that would be master. Alternatively, if another branch is checked out of the Registry, for example a dummy branch, where there is no files, the active branch in ~/.julia/registries/SSI will also be dummy, and there will be no packages available. Therefore, the active branch in /path/to/Registry must be master.

Now, when I attempt to add a new package to the registry, this error occurs:

julia> register("ErrorTypes", registry="SSI", repo="[email protected]:jakobnissen/ErrorTypes.jl.git")
┌ Info: Registering package
│   package_path = "/Users/jakobnissen/code/ErrorTypes.jl"
│   registry_path = "/Users/jakobnissen/.julia/registries/SSI"
│   package_repo = "[email protected]:jakobnissen/ErrorTypes.jl.git"
│   uuid = UUID("7f495686-c6d2-4c77-9e8e-e4c865675f9d")
│   version = v"0.5.1"
│   tree_hash = "7657192c03020baafb44aa1063da118842a7d84f"
└   subdir = ""
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 16 threads
Compressing objects: 100% (6/6), done.
Writing objects: 100% (9/9), 931 bytes | 931.00 KiB/s, done.
Total 9 (delta 2), reused 0 (delta 0), pack-reused 0
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.

This is a Git error. It happens because LocalRegistry makes a commit in the copied registry at ~/.julia/registries/SSI, and then tries to push the commit to the remote (at /path/to/Registry). However, Git goes not allow you to push to a checked out branch.

In other words: To add a repository, the master branch needs to be checked out, but to add/update packages, the master branch must not be checked out. This requires the user to manually switch between branches, which can be quite disruptive when many people are working on the same repo.

This can be solved by either

  1. LocalRegistry automatically switches branch to a new, empty branch, when attempting to modify the repo, or
  2. LocalRegistry requires the upstream registry to have set the git value git config --bool core.bare true. This allows pushing to the checked out branch.

jakobnissen avatar Aug 16 '21 10:08 jakobnissen

From googling it seems like you also have the option to configure receive.denyCurrentBranch to updateInstead but the intention is that the remote should be bare and it frankly didn't occur to me that people would consider using non-bare repositories upstream. For that case your best current option is to register with push = false and juggle with branches on your own.

I do have plans to add the option to push to custom branches, but with the purpose to allow PR-based workflows. I haven't needed it myself yet though.

GunnarFarneback avatar Aug 16 '21 18:08 GunnarFarneback

It is completely fine that the repo should be bare. The issue is that it is not created as bare using LocalRegistry, it is not documented that it should be bare, and it is not checked whether it is bare when pushing. For me the issue was that I didn't know what a bare repo was, and so using LocalRegistry as stated in the docs didn't work, and threw a (to me) obscure error.

Perhaps that can be some actionable points?:

  • Initialize the repo as bare with create_registry
  • Document the repo needs to be bare
  • If possible, check if the repo is bare when committing to it, and throw an informative error if it isn't

jakobnissen avatar Aug 16 '21 19:08 jakobnissen

  • Initialize the repo as bare with create_registry

create_registry is intended to create a checked out registry so it shouldn't be bare. The repo argument should point to a bare upstream though.

  • Document the repo needs to be bare

Yes, this should be documented.

  • If possible, check if the repo is bare when committing to it, and throw an informative error if it isn't

This is a good idea if it can be done sufficiently easily, robustly and is not unduly slow.

Not exactly related to this issue, but the work in progress tutorial https://github.com/GunnarFarneback/LocalRegistry.jl/blob/tutorial/docs/tutorials/create_registry_github.md may help out a bit as well.

GunnarFarneback avatar Aug 16 '21 20:08 GunnarFarneback

create_registry is intended to create a checked out registry so it shouldn't be bare. The repo argument should point to a bare upstream though.

Ah. Okay, so you need to point to an empty git repository if it's local? That would be nice to add in the docs :)

jakobnissen avatar Aug 16 '21 20:08 jakobnissen