From 86e4e5b9c3a65d2a02dd0ea5a580a1620bd7c6f1 Mon Sep 17 00:00:00 2001 From: "Kyle J. McKay" Date: Mon, 14 Jun 2021 11:56:03 -0700 Subject: [PATCH] init: provide config option for initial branch of push projects Add new $Girocco::Config::initial_branch configuration option that allows the name of the initial unborn branch in newly created push projects to be configured. Make this configuration option work with any Git version. To provide consistency, if the option is not set, is the empty string or is invalid, always use the historical name for the initial unborn branch in a newly created Git repository (i.e. "master"). Even without this support in place, if a different first branch (other than the unborn branch that `HEAD` points at) gets pushed to a newly created empty push project, `HEAD` will be automatically updated to point to that branch. With this support in place and a different initial branch name set, one would hope that cloning that initial, empty push project would automatically configure the initial branch name to match thus making everything just a tad bit more convenient. Unfortunately the reality bites. Git fails to send any capabilities at all when a project has no refs and the operation is not a push (in contrast to JGit). Furthermore, Git will always omit the symref=HEAD:... capability when the HEAD symbolic-ref is still unborn. Additionally, even if a special setup is used that does send the initial capabilities (like JGit) and does include the symref=HEAD: capability even when the HEAD symbolic-ref is still unborn, Git will ignore it when setting up the empty repository clone! Major FAIL for Git! Signed-off-by: Kyle J. McKay --- Girocco/Config.pm | 18 ++++++++++++++++++ Girocco/Project.pm | 14 +++++++++++++- Girocco/Validator.pm | 3 +++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/Girocco/Config.pm b/Girocco/Config.pm index 3367722..1441bb9 100644 --- a/Girocco/Config.pm +++ b/Girocco/Config.pm @@ -325,6 +325,24 @@ our $mailsh_sizelimit = 512; # +## ---------------------- +## Miscellaneous Settings +## ---------------------- +# + +# When creating a push project the initial branch will, by default, be +# set to refs/heads/$initial_branch even on Git versions that do not have +# support for `git init --initial-branch=$initial_branch`. +# If this value is unset or invalid the default initial branch will always +# be "master". Note that this only applies to newly created "push" projects; +# mirror projects and "adopted" projects ignore this setting. +# RECOMMENDED VALUE: whatever-your-favored-initial-branch-name-is +#our $initial_branch = "supercalifragilisticexpialidocious"; +#our $initial_branch = "frabjous"; +our $initial_branch = undef; + + +# ## ------------------- ## Foreign VCS mirrors ## ------------------- diff --git a/Girocco/Project.pm b/Girocco/Project.pm index 23e2266..3ed7d04 100644 --- a/Girocco/Project.pm +++ b/Girocco/Project.pm @@ -1080,6 +1080,7 @@ sub _setup { chmod(02777, $self->{path}) or die "chmod 02777 $self->{path} failed: $!"; } delete $ENV{GIT_OBJECT_DIRECTORY}; + delete $ENV{GIT_TEST_DEFAULT_INITIAL_BRANCH_NAME}; $ENV{'GIT_TEMPLATE_DIR'} = $Girocco::Config::chroot.'/var/empty'; system($Girocco::Config::git_bin, '--git-dir='.$self->{path}, 'init', '--quiet', '--bare', '--shared='.$self->shared_mode()) == 0 or die "git init $self->{path} failed: $?"; @@ -1224,6 +1225,17 @@ sub conjure { or die "create-personal-mob-area $self->{name} failed"; } $self->perm_initialize; + # set initial HEAD if it's not already set to the configured initial branch name + my $def_head = $self->{HEAD}; + defined($def_head) && $def_head ne "" or $def_head = $Girocco::Config::initial_branch; + defined($def_head) or $def_head = ""; + $def_head ne "" && $def_head !~ /^\/|^\.|[\x00-\x1f \x7f\[\[~^"'"<>*?\\:]|\@\{|\.\.|\.lock$|\.$|\/$/ or + $def_head = "master"; + my $cur_head = read_HEAD_ref($self->{path}); + defined($cur_head) && $cur_head =~ m{^refs/heads/\Q$def_head\E$} or + $self->set_HEAD($def_head); + $self->{HEAD} = $def_head; + 1; } sub clone { @@ -1648,7 +1660,7 @@ sub set_HEAD { my $self = shift; my $newHEAD = shift; # Cursory checks only -- if you want to break your HEAD, be my guest - if ($newHEAD =~ /^\/|^\.|[\x00-\x1f \x7f\[~^'<>*?\\:]|\@\{|\.\.|\.lock$|\.$|\/$/) { + if ($newHEAD =~ /^\/|^\.|[\x00-\x1f \x7f\[\[~^"'"<>*?\\:]|\@\{|\.\.|\.lock$|\.$|\/$/) { die "grossly invalid new HEAD: $newHEAD"; } system($Girocco::Config::git_bin, "--git-dir=$self->{path}", 'symbolic-ref', 'HEAD', "refs/heads/$newHEAD"); diff --git a/Girocco/Validator.pm b/Girocco/Validator.pm index 4a755c7..6cd7aac 100644 --- a/Girocco/Validator.pm +++ b/Girocco/Validator.pm @@ -73,6 +73,9 @@ $project_edit_timeout =~ /^[1-9][0-9]*$/ or die "Girocco::Config: \$max_readme_size must be a whole number"; defined($mailsh_sizelimit) && $mailsh_sizelimit =~ /^[1-9][0-9]*$/ or die "Girocco::Config: \$mailsh_sizelimit must be a positive number"; +!defined($initial_branch) || $initial_branch eq "" || + $initial_branch !~ /^\/|^\.|[\x00-\x1f \x7f\[\[~^"'"<>*?\\:]|\@\{|\.\.|\.lock$|\.$|\/$/ or + die "Girocco::Config: \$initial_branch grossly invalid: $initial_branch"; $admincc = $admincc ? 1 : 0; $rootcert = "$certsdir/girocco_root_crt.pem" if $httpspushurl && !$rootcert; $clientcert = "$certsdir/girocco_client_crt.pem" if $httpspushurl && !$clientcert; -- 2.11.4.GIT