Implement repository removal/deletion

This commit is contained in:
Drew DeVault 2020-04-01 14:47:47 -04:00
parent d9b06b8092
commit 6e3810a76c
9 changed files with 123 additions and 59 deletions

View File

@ -153,3 +153,39 @@ def summary_POST(owner, project_name, repo_id):
db.session.commit()
return redirect(url_for("projects.summary_GET",
owner=owner.canonical_name, project_name=project.name))
@sources.route("/<owner>/<project_name>/sources/delete/<int:repo_id>")
@loginrequired
def delete_GET(owner, project_name, repo_id):
owner, project = get_project(owner, project_name, ProjectAccess.write)
repo = (SourceRepo.query
.filter(SourceRepo.id == repo_id)
.filter(SourceRepo.project_id == project.id)).one_or_none()
if not repo:
abort(404)
return render_template("resource-delete.html", view="sources",
owner=owner, project=project, resource=repo,
resource_type=repo.repo_type.value + " repository")
@sources.route("/<owner>/<project_name>/sources/delete/<int:repo_id>",
methods=["POST"])
@loginrequired
def delete_POST(owner, project_name, repo_id):
owner, project = get_project(owner, project_name, ProjectAccess.write)
repo = (SourceRepo.query
.filter(SourceRepo.id == repo_id)
.filter(SourceRepo.project_id == project.id)).one_or_none()
if not repo:
abort(404)
if project.summary_repo_id == repo.id:
project.summary_repo_id = None
db.session.delete(repo)
valid = Validation(request)
delete_remote = valid.optional("delete-remote") == "on"
if delete_remote:
git.delete_repo(owner, repo.name)
db.session.commit()
return redirect(url_for("projects.summary_GET",
owner=owner.canonical_name, project_name=project.name))

View File

@ -60,6 +60,12 @@ class GitService(SrhtService):
"visibility": "public", # TODO: Should this be different?
})
def delete_repo(self, user, repo_name):
r = self.session.delete(f"{_gitsrht}/api/repos/{repo_name}",
headers=get_authorization(user))
if r.status_code != 204:
raise Exception(r.text)
def ensure_user_webhooks(self, user):
config = {
origin + url_for("webhooks.git_repo"):

View File

@ -0,0 +1,17 @@
{% extends "layout.html" %}
{% block body %}
<div class="header-tabbed">
<div class="container">
{% include 'project-nav.html' %}
</div>
</div>
{% if project.description %}
<div class="header-extension">
<div class="container">
{{ project.description }}
</div>
</div>
{% endif %}
{% block content %}
{% endblock %}
{% endblock %}

View File

@ -1,17 +1,5 @@
{% extends "layout.html" %}
{% block body %}
<div class="header-tabbed">
<div class="container">
{% include 'project-nav.html' %}
</div>
</div>
{% if project.description %}
<div class="header-extension">
<div class="container">
{{ project.description }}
</div>
</div>
{% endif %}
{% extends "project-base.html" %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-12 event-list">

View File

@ -0,0 +1,40 @@
{% extends "project-base.html" %}
{% block content %}
<form class="container" method="POST">
{{csrf_token()}}
<div class="row">
<div class="col-md-12">
<p>
Do you really want to remove the
<a href="{{resource.url()}}">{{resource.name}}</a>
{{resource_type}} from the {{project.name}} project?
</p>
{# Deletion is complicated, some services don't support it yet #}
{% if not undeletable %}
<div class="event-list">
<div class="event">
<div class="form-check form-group">
<label class="form-check-label">
<input
class="form-check-input"
type="checkbox"
name="delete-remote">
Remove from the project <em>and</em> delete the {{resource_type}}
(<span class="text-danger">this cannot be undone</span>)
</label>
</div>
</div>
</div>
{% endif %}
<div class="form-group">
<button type="submit" class="btn btn-danger">
Remove this {{resource_type}} {{icon('caret-right')}}
</button>
<a href="#" class="btn btn-default">
Cancel {{icon('caret-right')}}
</a>
</div>
</div>
</div>
</form>
{% endblock %}

View File

@ -1,17 +1,5 @@
{% extends "layout.html" %}
{% block body %}
<div class="header-tabbed">
<div class="container">
{% include 'project-nav.html' %}
</div>
</div>
{% if project.description %}
<div class="header-extension">
<div class="container">
{{ project.description }}
</div>
</div>
{% endif %}
{% extends "project-base.html" %}
{% block content %}
<form class="container">
<div class="row">
{% if current_user and current_user.id == owner.id %}

View File

@ -18,7 +18,7 @@
class="nav-link"
href="{{url_for("projects.summary_GET",
owner=owner.canonical_name, project_name=project.name)}}"
>{{icon('caret-left')}}&nbsp;back</a>
>{{icon('caret-left')}}&nbsp;cancel</a>
</li>
</ul>
</div>

View File

@ -1,17 +1,5 @@
{% extends "layout.html" %}
{% block body %}
<div class="header-tabbed">
<div class="container">
{% include 'project-nav.html' %}
</div>
</div>
{% if project.description %}
<div class="header-extension">
<div class="container">
{{ project.description }}
</div>
</div>
{% endif %}
{% extends "project-base.html" %}
{% block content %}
<div class="container">
<div class="row">
<div class="col-md-12 event-list">
@ -57,16 +45,13 @@
Use README.md {{icon('caret-right')}}
</button>
</form>
<form
class="d-inline"
method="POST"
action="#TODO"
>
{{csrf_token()}}
<button class="btn btn-danger">
Remove repository {{icon('caret-right')}}
</button>
</form>
<a
class="btn btn-danger"
href="{{url_for("sources.delete_POST",
owner=project.owner.canonical_name,
project_name=project.name,
repo_id=repo.id)}}"
>Remove repository {{icon('caret-right')}}</a>
</div>
{% endfor %}
{{pagination()}}

View File

@ -17,19 +17,23 @@ class Event(Base):
project = sa.orm.relationship("Project", backref=sa.orm.backref("events"))
"""The project implicated in this event"""
user_id = sa.Column(sa.Integer, sa.ForeignKey("user.id"), nullable=False)
user = sa.orm.relationship("User", backref=sa.orm.backref("events"))
user_id = sa.Column(sa.Integer,
sa.ForeignKey("user.id", ondelete="CASCADE"), nullable=False)
user = sa.orm.relationship("User", backref=sa.orm.backref("events"),
cascade="all, delete")
"""The user implicated in this event"""
event_type = sa.Column(sau.ChoiceType(EventType, impl=sa.String()),
nullable=False)
source_repo_id = sa.Column(sa.Integer, sa.ForeignKey("source_repo.id"))
source_repo = sa.orm.relationship("SourceRepo")
source_repo_id = sa.Column(sa.Integer,
sa.ForeignKey("source_repo.id", ondelete="CASCADE"))
source_repo = sa.orm.relationship("SourceRepo", cascade="all, delete")
"""The source repository implicated in this event, if applicable"""
mailing_list_id = sa.Column(sa.Integer, sa.ForeignKey("mailing_list.id"))
mailing_list = sa.orm.relationship("MailingList")
mailing_list_id = sa.Column(sa.Integer,
sa.ForeignKey("mailing_list.id", ondelete="CASCADE"))
mailing_list = sa.orm.relationship("MailingList", cascade="all, delete")
"""The mailing list implicated in this event, if applicable"""
external_source = sa.Column(sa.Unicode) # e.g. "lists.sr.ht"