mirror of
				https://github.com/go-gitea/gitea
				synced 2025-10-31 19:38:23 +00:00 
			
		
		
		
	Use a predictiable fork URL to allow forking repositories without providing a repo ID (#29519)
Close #29512 The "fork" URL: * Before: `/repo/fork/{RepoID}` * After: `/{OwnerName}/{RepoName}/fork`
This commit is contained in:
		| @@ -112,7 +112,7 @@ func getRepository(ctx *context.Context, repoID int64) *repo_model.Repository { | |||||||
| } | } | ||||||
|  |  | ||||||
| func getForkRepository(ctx *context.Context) *repo_model.Repository { | func getForkRepository(ctx *context.Context) *repo_model.Repository { | ||||||
| 	forkRepo := getRepository(ctx, ctx.ParamsInt64(":repoid")) | 	forkRepo := ctx.Repo.Repository | ||||||
| 	if ctx.Written() { | 	if ctx.Written() { | ||||||
| 		return nil | 		return nil | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -956,10 +956,6 @@ func registerRoutes(m *web.Route) { | |||||||
| 		m.Post("/create", web.Bind(forms.CreateRepoForm{}), repo.CreatePost) | 		m.Post("/create", web.Bind(forms.CreateRepoForm{}), repo.CreatePost) | ||||||
| 		m.Get("/migrate", repo.Migrate) | 		m.Get("/migrate", repo.Migrate) | ||||||
| 		m.Post("/migrate", web.Bind(forms.MigrateRepoForm{}), repo.MigratePost) | 		m.Post("/migrate", web.Bind(forms.MigrateRepoForm{}), repo.MigratePost) | ||||||
| 		m.Group("/fork", func() { |  | ||||||
| 			m.Combo("/{repoid}").Get(repo.Fork). |  | ||||||
| 				Post(web.Bind(forms.CreateRepoForm{}), repo.ForkPost) |  | ||||||
| 		}, context.RepoIDAssignment(), context.UnitTypes(), reqRepoCodeReader) |  | ||||||
| 		m.Get("/search", repo.SearchRepo) | 		m.Get("/search", repo.SearchRepo) | ||||||
| 	}, reqSignIn) | 	}, reqSignIn) | ||||||
|  |  | ||||||
| @@ -1255,6 +1251,8 @@ func registerRoutes(m *web.Route) { | |||||||
| 			m.Post("/delete", repo.DeleteBranchPost) | 			m.Post("/delete", repo.DeleteBranchPost) | ||||||
| 			m.Post("/restore", repo.RestoreBranchPost) | 			m.Post("/restore", repo.RestoreBranchPost) | ||||||
| 		}, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty) | 		}, context.RepoMustNotBeArchived(), reqRepoCodeWriter, repo.MustBeNotEmpty) | ||||||
|  |  | ||||||
|  | 		m.Combo("/fork", reqRepoCodeReader).Get(repo.Fork).Post(web.Bind(forms.CreateRepoForm{}), repo.ForkPost) | ||||||
| 	}, reqSignIn, context.RepoAssignment, context.UnitTypes()) | 	}, reqSignIn, context.RepoAssignment, context.UnitTypes()) | ||||||
|  |  | ||||||
| 	// Tags | 	// Tags | ||||||
|   | |||||||
| @@ -408,26 +408,6 @@ func repoAssignment(ctx *Context, repo *repo_model.Repository) { | |||||||
| 	ctx.Data["IsEmptyRepo"] = ctx.Repo.Repository.IsEmpty | 	ctx.Data["IsEmptyRepo"] = ctx.Repo.Repository.IsEmpty | ||||||
| } | } | ||||||
|  |  | ||||||
| // RepoIDAssignment returns a handler which assigns the repo to the context. |  | ||||||
| func RepoIDAssignment() func(ctx *Context) { |  | ||||||
| 	return func(ctx *Context) { |  | ||||||
| 		repoID := ctx.ParamsInt64(":repoid") |  | ||||||
|  |  | ||||||
| 		// Get repository. |  | ||||||
| 		repo, err := repo_model.GetRepositoryByID(ctx, repoID) |  | ||||||
| 		if err != nil { |  | ||||||
| 			if repo_model.IsErrRepoNotExist(err) { |  | ||||||
| 				ctx.NotFound("GetRepositoryByID", nil) |  | ||||||
| 			} else { |  | ||||||
| 				ctx.ServerError("GetRepositoryByID", err) |  | ||||||
| 			} |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		repoAssignment(ctx, repo) |  | ||||||
| 	} |  | ||||||
| } |  | ||||||
|  |  | ||||||
| // RepoAssignment returns a middleware to handle repository assignment | // RepoAssignment returns a middleware to handle repository assignment | ||||||
| func RepoAssignment(ctx *Context) context.CancelFunc { | func RepoAssignment(ctx *Context) context.CancelFunc { | ||||||
| 	if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce { | 	if _, repoAssignmentOnce := ctx.Data["repoAssignmentExecuted"]; repoAssignmentOnce { | ||||||
|   | |||||||
| @@ -82,7 +82,7 @@ | |||||||
| 									{{/*else is not required here, because the button shouldn't link to any site if you can't create a fork*/}} | 									{{/*else is not required here, because the button shouldn't link to any site if you can't create a fork*/}} | ||||||
| 									{{end}} | 									{{end}} | ||||||
| 								{{else if not $.UserAndOrgForks}} | 								{{else if not $.UserAndOrgForks}} | ||||||
| 									href="{{AppSubUrl}}/repo/fork/{{.ID}}" | 									href="{{$.RepoLink}}/fork" | ||||||
| 								{{else}} | 								{{else}} | ||||||
| 									data-modal="#fork-repo-modal" | 									data-modal="#fork-repo-modal" | ||||||
| 								{{end}} | 								{{end}} | ||||||
| @@ -103,7 +103,7 @@ | |||||||
| 									</div> | 									</div> | ||||||
| 									{{if $.CanSignedUserFork}} | 									{{if $.CanSignedUserFork}} | ||||||
| 									<div class="divider"></div> | 									<div class="divider"></div> | ||||||
| 									<a href="{{AppSubUrl}}/repo/fork/{{.ID}}">{{ctx.Locale.Tr "repo.fork_to_different_account"}}</a> | 									<a href="{{$.RepoLink}}/fork">{{ctx.Locale.Tr "repo.fork_to_different_account"}}</a> | ||||||
| 									{{end}} | 									{{end}} | ||||||
| 								</div> | 								</div> | ||||||
| 							</div> | 							</div> | ||||||
|   | |||||||
| @@ -29,14 +29,14 @@ func testRepoFork(t *testing.T, session *TestSession, ownerName, repoName, forkO | |||||||
|  |  | ||||||
| 	// Step2: click the fork button | 	// Step2: click the fork button | ||||||
| 	htmlDoc := NewHTMLParser(t, resp.Body) | 	htmlDoc := NewHTMLParser(t, resp.Body) | ||||||
| 	link, exists := htmlDoc.doc.Find("a.ui.button[href^=\"/repo/fork/\"]").Attr("href") | 	link, exists := htmlDoc.doc.Find(`a.ui.button[href*="/fork"]`).Attr("href") | ||||||
| 	assert.True(t, exists, "The template has changed") | 	assert.True(t, exists, "The template has changed") | ||||||
| 	req = NewRequest(t, "GET", link) | 	req = NewRequest(t, "GET", link) | ||||||
| 	resp = session.MakeRequest(t, req, http.StatusOK) | 	resp = session.MakeRequest(t, req, http.StatusOK) | ||||||
|  |  | ||||||
| 	// Step3: fill the form of the forking | 	// Step3: fill the form of the forking | ||||||
| 	htmlDoc = NewHTMLParser(t, resp.Body) | 	htmlDoc = NewHTMLParser(t, resp.Body) | ||||||
| 	link, exists = htmlDoc.doc.Find("form.ui.form[action^=\"/repo/fork/\"]").Attr("action") | 	link, exists = htmlDoc.doc.Find(`form.ui.form[action*="/fork"]`).Attr("action") | ||||||
| 	assert.True(t, exists, "The template has changed") | 	assert.True(t, exists, "The template has changed") | ||||||
| 	_, exists = htmlDoc.doc.Find(fmt.Sprintf(".owner.dropdown .item[data-value=\"%d\"]", forkOwner.ID)).Attr("data-value") | 	_, exists = htmlDoc.doc.Find(fmt.Sprintf(".owner.dropdown .item[data-value=\"%d\"]", forkOwner.ID)).Attr("data-value") | ||||||
| 	assert.True(t, exists, fmt.Sprintf("Fork owner '%s' is not present in select box", forkOwnerName)) | 	assert.True(t, exists, fmt.Sprintf("Fork owner '%s' is not present in select box", forkOwnerName)) | ||||||
| @@ -70,6 +70,6 @@ func TestRepoForkToOrg(t *testing.T) { | |||||||
| 	req := NewRequest(t, "GET", "/user2/repo1") | 	req := NewRequest(t, "GET", "/user2/repo1") | ||||||
| 	resp := session.MakeRequest(t, req, http.StatusOK) | 	resp := session.MakeRequest(t, req, http.StatusOK) | ||||||
| 	htmlDoc := NewHTMLParser(t, resp.Body) | 	htmlDoc := NewHTMLParser(t, resp.Body) | ||||||
| 	_, exists := htmlDoc.doc.Find("a.ui.button[href^=\"/repo/fork/\"]").Attr("href") | 	_, exists := htmlDoc.doc.Find(`a.ui.button[href*="/fork"]`).Attr("href") | ||||||
| 	assert.False(t, exists, "Forking should not be allowed anymore") | 	assert.False(t, exists, "Forking should not be allowed anymore") | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user