M gitsrht-shell/main.go => gitsrht-shell/main.go +5 -0
@@ 299,6 299,11 @@ func main() {
notFound("git init", err)
}
+ if err = exec.Command("git", "-C", path, "config",
+ "receive.denyDeleteCurrent", "ignore").Run(); err != nil {
+
+ notFound("git config", err)
+ }
if err = exec.Command("ln", "-s", postUpdate,
gopath.Join(path, "hooks", "update")).Run(); err != nil {
A gitsrht/alembic/versions/3c1285bb23e2_allow_deleting_default_branch.py => gitsrht/alembic/versions/3c1285bb23e2_allow_deleting_default_branch.py +42 -0
@@ 0,0 1,42 @@
+"""Allow deleting default branch
+
+Revision ID: 3c1285bb23e2
+Revises: 163fc2d2a2ea
+Create Date: 2020-07-28 12:04:39.751225
+
+"""
+
+# revision identifiers, used by Alembic.
+revision = '3c1285bb23e2'
+down_revision = '163fc2d2a2ea'
+
+import subprocess
+from alembic import op
+from sqlalchemy.orm import sessionmaker
+from gitsrht.types import Repository
+try:
+ from tqdm import tqdm
+except ImportError:
+ def tqdm(iterable):
+ yield from iterable
+
+Session = sessionmaker()
+
+
+def upgrade():
+ bind = op.get_bind()
+ session = Session(bind=bind)
+ print("Setting receive.denyDeleteCurrent=ignore")
+ for repo in tqdm(session.query(Repository).all()):
+ subprocess.run(["git", "config", "receive.denyDeleteCurrent", "ignore"],
+ check=True, cwd=repo.path,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+
+
+def downgrade():
+ bind = op.get_bind()
+ session = Session(bind=bind)
+ for repo in tqdm(session.query(Repository).all()):
+ subprocess.run(["git", "config", "--unset", "receive.denyDeleteCurrent"],
+ check=True, cwd=repo.path,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
M gitsrht/repos.py => gitsrht/repos.py +5 -0
@@ 90,6 90,11 @@ class GitRepoApi(SimpleRepoApi):
stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.run(["git", "config", "srht.repo-id", str(repo.id)], check=True,
cwd=repo.path, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
+ # We handle this ourselves in the post-update hook, and git's
+ # default behaviour is to print a large notice and reject the push entirely
+ subprocess.run(["git", "config", "receive.denyDeleteCurrent", "ignore"],
+ check=True, cwd=repo.path,
+ stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
subprocess.run(["ln", "-s",
post_update,
os.path.join(repo.path, "hooks", "pre-receive")