Provide option to unlink a fork (#11858)

* Provide option to unlink a fork

Fix #4566

Signed-off-by: Andrew Thornton <art27@cantab.net>

* Apply suggestions from code review

Co-authored-by: techknowlogick <matti@mdranta.net>

* Add check that user can create repo

Signed-off-by: Andrew Thornton <art27@cantab.net>

* as per @cirnoT

Signed-off-by: Andrew Thornton <art27@cantab.net>

Co-authored-by: techknowlogick <matti@mdranta.net>
This commit is contained in:
zeripath 2020-07-02 15:09:09 +01:00 committed by GitHub
parent a87a64e6a1
commit 482ba937ed
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 124 additions and 48 deletions

View file

@ -209,19 +209,9 @@ func (repo *Repository) SanitizedOriginalURL() string {
// ColorFormat returns a colored string to represent this repo // ColorFormat returns a colored string to represent this repo
func (repo *Repository) ColorFormat(s fmt.State) { func (repo *Repository) ColorFormat(s fmt.State) {
var ownerName interface{}
if repo.OwnerName != "" {
ownerName = repo.OwnerName
} else if repo.Owner != nil {
ownerName = repo.Owner.Name
} else {
ownerName = log.NewColoredIDValue(strconv.FormatInt(repo.OwnerID, 10))
}
log.ColorFprintf(s, "%d:%s/%s", log.ColorFprintf(s, "%d:%s/%s",
log.NewColoredIDValue(repo.ID), log.NewColoredIDValue(repo.ID),
ownerName, repo.OwnerName,
repo.Name) repo.Name)
} }

View file

@ -1382,6 +1382,11 @@ settings.convert_desc = You can convert this mirror into a regular repository. T
settings.convert_notices_1 = This operation will convert the mirror into a regular repository and cannot be undone. settings.convert_notices_1 = This operation will convert the mirror into a regular repository and cannot be undone.
settings.convert_confirm = Convert Repository settings.convert_confirm = Convert Repository
settings.convert_succeed = The mirror has been converted into a regular repository. settings.convert_succeed = The mirror has been converted into a regular repository.
settings.convert_fork = Convert to Regular Repository
settings.convert_fork_desc = You can convert this fork into a regular repository. This cannot be undone.
settings.convert_fork_notices_1 = This operation will convert the fork into a regular repository and cannot be undone.
settings.convert_fork_confirm = Convert Repository
settings.convert_fork_succeed = The fork has been converted into a regular repository.
settings.transfer = Transfer Ownership settings.transfer = Transfer Ownership
settings.transfer_desc = Transfer this repository to a user or to an organization for which you have administrator rights. settings.transfer_desc = Transfer this repository to a user or to an organization for which you have administrator rights.
settings.transfer_notices_1 = - You will lose access to the repository if you transfer it to an individual user. settings.transfer_notices_1 = - You will lose access to the repository if you transfer it to an individual user.

View file

@ -356,9 +356,46 @@ func SettingsPost(ctx *context.Context, form auth.RepoSettingForm) {
ctx.ServerError("DeleteMirrorByRepoID", err) ctx.ServerError("DeleteMirrorByRepoID", err)
return return
} }
log.Trace("Repository converted from mirror to regular: %s/%s", ctx.Repo.Owner.Name, repo.Name) log.Trace("Repository converted from mirror to regular: %s", repo.FullName())
ctx.Flash.Success(ctx.Tr("repo.settings.convert_succeed")) ctx.Flash.Success(ctx.Tr("repo.settings.convert_succeed"))
ctx.Redirect(setting.AppSubURL + "/" + ctx.Repo.Owner.Name + "/" + repo.Name) ctx.Redirect(repo.Link())
case "convert_fork":
if !ctx.Repo.IsOwner() {
ctx.Error(404)
return
}
if err := repo.GetOwner(); err != nil {
ctx.ServerError("Convert Fork", err)
return
}
if repo.Name != form.RepoName {
ctx.RenderWithErr(ctx.Tr("form.enterred_invalid_repo_name"), tplSettingsOptions, nil)
return
}
if !repo.IsFork {
ctx.Error(404)
return
}
if !ctx.Repo.Owner.CanCreateRepo() {
ctx.Flash.Error(ctx.Tr("repo.form.reach_limit_of_creation", ctx.User.MaxCreationLimit()))
ctx.Redirect(repo.Link() + "/settings")
return
}
repo.IsFork = false
repo.ForkID = 0
if err := models.UpdateRepository(repo, false); err != nil {
log.Error("Unable to update repository %-v whilst converting from fork", repo)
ctx.ServerError("Convert Fork", err)
return
}
log.Trace("Repository converted from fork to regular: %s", repo.FullName())
ctx.Flash.Success(ctx.Tr("repo.settings.convert_fork_succeed"))
ctx.Redirect(repo.Link())
case "transfer": case "transfer":
if !ctx.Repo.IsOwner() { if !ctx.Repo.IsOwner() {

View file

@ -358,17 +358,28 @@
</h4> </h4>
<div class="ui attached warning table danger segment"> <div class="ui attached warning table danger segment">
{{if .Repository.IsMirror}} {{if .Repository.IsMirror}}
<div class="item"> <div class="item">
<div class="ui right"> <div class="ui right">
<button class="ui basic red show-modal button" data-modal="#convert-repo-modal">{{.i18n.Tr "repo.settings.convert"}}</button> <button class="ui basic red show-modal button" data-modal="#convert-mirror-repo-modal">{{.i18n.Tr "repo.settings.convert"}}</button>
</div>
<div>
<h5>{{.i18n.Tr "repo.settings.convert"}}</h5>
<p>{{.i18n.Tr "repo.settings.convert_desc"}}</p>
</div>
</div> </div>
<div> <div class="ui divider"></div>
<h5>{{.i18n.Tr "repo.settings.convert"}}</h5> {{end}}
<p>{{.i18n.Tr "repo.settings.convert_desc"}}</p> {{if and .Repository.IsFork .Repository.Owner.CanCreateRepo}}
<div class="item">
<div class="ui right">
<button class="ui basic red show-modal button" data-modal="#convert-fork-repo-modal">{{.i18n.Tr "repo.settings.convert_fork"}}</button>
</div>
<div>
<h5>{{.i18n.Tr "repo.settings.convert_fork"}}</h5>
<p>{{.i18n.Tr "repo.settings.convert_fork_desc"}}</p>
</div>
</div> </div>
</div> <div class="ui divider"></div>
<div class="ui divider"></div>
{{end}} {{end}}
<div class="item"> <div class="item">
<div class="ui right"> <div class="ui right">
@ -437,37 +448,67 @@
{{if .Permission.IsOwner}} {{if .Permission.IsOwner}}
{{if .Repository.IsMirror}} {{if .Repository.IsMirror}}
<div class="ui small modal" id="convert-repo-modal"> <div class="ui small modal" id="convert-mirror-repo-modal">
<div class="header"> <div class="header">
{{.i18n.Tr "repo.settings.convert"}} {{.i18n.Tr "repo.settings.convert"}}
</div>
<div class="content">
<div class="ui warning message text left">
{{.i18n.Tr "repo.settings.convert_notices_1"}}
</div> </div>
<form class="ui form" action="{{.Link}}" method="post"> <div class="content">
{{.CsrfTokenHtml}} <div class="ui warning message text left">
<input type="hidden" name="action" value="convert"> {{.i18n.Tr "repo.settings.convert_notices_1"}}
<div class="field">
<label>
{{.i18n.Tr "repo.settings.transfer_form_title"}}
<span class="text red">{{.Repository.Name}}</span>
</label>
</div>
<div class="required field">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" required>
</div> </div>
<form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="convert">
<div class="field">
<label>
{{.i18n.Tr "repo.settings.transfer_form_title"}}
<span class="text red">{{.Repository.Name}}</span>
</label>
</div>
<div class="required field">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" required>
</div>
<div class="text right actions"> <div class="text right actions">
<div class="ui cancel button">{{.i18n.Tr "settings.cancel"}}</div> <div class="ui cancel button">{{.i18n.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.i18n.Tr "repo.settings.convert_confirm"}}</button> <button class="ui red button">{{.i18n.Tr "repo.settings.convert_confirm"}}</button>
</div> </div>
</form> </form>
</div>
</div> </div>
</div>
{{end}} {{end}}
{{if and .Repository.IsFork .Repository.Owner.CanCreateRepo}}
<div class="ui small modal" id="convert-fork-repo-modal">
<div class="header">
{{.i18n.Tr "repo.settings.convert_fork"}}
</div>
<div class="content">
<div class="ui warning message text left">
{{.i18n.Tr "repo.settings.convert_fork_notices_1"}}
</div>
<form class="ui form" action="{{.Link}}" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="action" value="convert_fork">
<div class="field">
<label>
{{.i18n.Tr "repo.settings.transfer_form_title"}}
<span class="text red">{{.Repository.Name}}</span>
</label>
</div>
<div class="required field">
<label for="repo_name">{{.i18n.Tr "repo.repo_name"}}</label>
<input id="repo_name" name="repo_name" required>
</div>
<div class="text right actions">
<div class="ui cancel button">{{.i18n.Tr "settings.cancel"}}</div>
<button class="ui red button">{{.i18n.Tr "repo.settings.convert_fork_confirm"}}</button>
</div>
</form>
</div>
</div>
{{end}}
<div class="ui small modal" id="transfer-repo-modal"> <div class="ui small modal" id="transfer-repo-modal">
<div class="header"> <div class="header">
{{.i18n.Tr "repo.settings.transfer"}} {{.i18n.Tr "repo.settings.transfer"}}

View file

@ -2796,7 +2796,10 @@
} }
#transfer-repo-modal, #transfer-repo-modal,
#delete-repo-modal { #delete-repo-modal,
#delete-wiki-modal,
#convert-fork-repo-modal,
#convert-mirror-repo-modal {
.ui.message { .ui.message {
width: 100% !important; width: 100% !important;
} }