From c9e5e38fcfa759a1d2578d1c7a56ac0e65e2bf78 Mon Sep 17 00:00:00 2001 From: evolvedlight Date: Sat, 4 Oct 2014 18:19:14 +0100 Subject: [PATCH 1/3] Initial cut of git fork --- models/models.go | 1 - models/repo.go | 127 ++++++++++++++++++++++++++++++++++++- routers/repo/repo.go | 9 +++ templates/repo/diff.tmpl | 2 + templates/repo/header.tmpl | 4 +- 5 files changed, 139 insertions(+), 4 deletions(-) diff --git a/models/models.go b/models/models.go index 570df0c114b9..60959c60e95f 100644 --- a/models/models.go +++ b/models/models.go @@ -20,7 +20,6 @@ import ( var ( x *xorm.Engine tables []interface{} - HasEngine bool DbCfg struct { diff --git a/models/repo.go b/models/repo.go index a79c2491cede..34b7cd83521a 100644 --- a/models/repo.go +++ b/models/repo.go @@ -174,6 +174,10 @@ func (repo *Repository) GetMirror() (err error) { return err } +func (repo *Repository) GetPath() string { + return RepoPath(repo.Owner.Name, repo.Name) +} + // DescriptionHtml does special handles to description and return HTML string. func (repo *Repository) DescriptionHtml() template.HTML { sanitize := func(s string) string { @@ -1224,6 +1228,127 @@ func IsStaring(uid, repoId int64) bool { return has } -func ForkRepository(repoName string, uid int64) { +func ForkRepository(u *User, oldRepo *Repository) (*Repository, error) { + isExist, err := IsRepositoryExist(u, oldRepo.Name) + if err != nil { + return nil, err + } else if isExist { + return nil, ErrRepoAlreadyExist + } + + sess := x.NewSession() + defer sess.Close() + if err = sess.Begin(); err != nil { + return nil, err + } + + repo := &Repository{ + OwnerId: u.Id, + Owner: u, + Name: oldRepo.Name, + LowerName: oldRepo.LowerName, + Description: oldRepo.Description, + IsPrivate: oldRepo.IsPrivate, + } + + if _, err = sess.Insert(repo); err != nil { + sess.Rollback() + return nil, err + } + + var t *Team // Owner team. + + mode := WRITABLE + + access := &Access{ + UserName: u.LowerName, + RepoName: path.Join(u.LowerName, repo.LowerName), + Mode: mode, + } + // Give access to all members in owner team. + if u.IsOrganization() { + t, err = u.GetOwnerTeam() + if err != nil { + sess.Rollback() + return nil, err + } + if err = t.GetMembers(); err != nil { + sess.Rollback() + return nil, err + } + for _, u := range t.Members { + access.Id = 0 + access.UserName = u.LowerName + if _, err = sess.Insert(access); err != nil { + sess.Rollback() + return nil, err + } + } + } else { + if _, err = sess.Insert(access); err != nil { + sess.Rollback() + return nil, err + } + } + + if _, err = sess.Exec( + "UPDATE `user` SET num_repos = num_repos + 1 WHERE id = ?", u.Id); err != nil { + sess.Rollback() + return nil, err + } + + // Update owner team info and count. + if u.IsOrganization() { + t.RepoIds += "$" + com.ToStr(repo.Id) + "|" + t.NumRepos++ + if _, err = sess.Id(t.Id).AllCols().Update(t); err != nil { + sess.Rollback() + return nil, err + } + } + + if err = sess.Commit(); err != nil { + return nil, err + } + + if u.IsOrganization() { + t, err := u.GetOwnerTeam() + if err != nil { + log.Error(4, "GetOwnerTeam: %v", err) + } else { + if err = t.GetMembers(); err != nil { + log.Error(4, "GetMembers: %v", err) + } else { + for _, u := range t.Members { + if err = WatchRepo(u.Id, repo.Id, true); err != nil { + log.Error(4, "WatchRepo2: %v", err) + } + } + } + } + } else { + if err = WatchRepo(u.Id, repo.Id, true); err != nil { + log.Error(4, "WatchRepo3: %v", err) + } + } + + if err = NewRepoAction(u, repo); err != nil { + log.Error(4, "NewRepoAction: %v", err) + } + + + repoPath := RepoPath(u.Name, repo.Name) + _, stderr, err := process.ExecTimeout(10*time.Minute, + fmt.Sprintf("ForkRepository: %s/%s", u.Name, repo.Name), + "git", "clone", oldRepo.GetPath(), repoPath) + + _, stderr, err = process.ExecDir(-1, + repoPath, fmt.Sprintf("CreateRepository(git update-server-info): %s", repoPath), + "git", "update-server-info") + if err != nil { + return nil, errors.New("CreateRepository(git update-server-info): " + stderr) + } + + return repo, nil } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index 5562a8400a7f..dac0c48b36e0 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -217,6 +217,15 @@ func Action(ctx *middleware.Context) { err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, true) case "unstar": err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, false) + case "fork": + repo, error := models.ForkRepository(ctx.User, ctx.Repo.Repository) + log.Info("Tried to fork a repo!") + log.Info("Repo thing is " + repo.Name) + if error != nil { + + ctx.Redirect(setting.AppSubUrl + "/" + ctx.User.Name + "/" + repo.Name) + return + } case "desc": if !ctx.Repo.IsOwner { ctx.Error(404) diff --git a/templates/repo/diff.tmpl b/templates/repo/diff.tmpl index 8e5efd146f1d..fa97073c6e96 100644 --- a/templates/repo/diff.tmpl +++ b/templates/repo/diff.tmpl @@ -96,6 +96,7 @@ {{range .Sections}} + Test: {{ .NumLines}} {{range .Lines}} + diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index 699e90461e1c..f0ebae5e6d05 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -44,14 +44,14 @@ - + \ No newline at end of file From 211dc74816c3832f973284f19ad0831da039ac76 Mon Sep 17 00:00:00 2001 From: evolvedlight Date: Fri, 10 Oct 2014 00:21:36 +0100 Subject: [PATCH 2/3] Got the fork count working --- models/repo.go | 16 ++++++++++++---- routers/repo/repo.go | 12 +++++++++--- 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/models/repo.go b/models/repo.go index 34b7cd83521a..2019542102d9 100644 --- a/models/repo.go +++ b/models/repo.go @@ -1307,9 +1307,7 @@ func ForkRepository(u *User, oldRepo *Repository) (*Repository, error) { } } - if err = sess.Commit(); err != nil { - return nil, err - } + if u.IsOrganization() { t, err := u.GetOwnerTeam() @@ -1335,7 +1333,16 @@ func ForkRepository(u *User, oldRepo *Repository) (*Repository, error) { if err = NewRepoAction(u, repo); err != nil { log.Error(4, "NewRepoAction: %v", err) } - + + if _, err = sess.Exec( + "UPDATE `repository` SET num_forks = num_forks + 1 WHERE id = ?", oldRepo.Id); err != nil { + sess.Rollback() + return nil, err + } + + if err = sess.Commit(); err != nil { + return nil, err + } repoPath := RepoPath(u.Name, repo.Name) _, stderr, err := process.ExecTimeout(10*time.Minute, @@ -1350,5 +1357,6 @@ func ForkRepository(u *User, oldRepo *Repository) (*Repository, error) { } return repo, nil + } diff --git a/routers/repo/repo.go b/routers/repo/repo.go index dac0c48b36e0..8b18eb25bf32 100644 --- a/routers/repo/repo.go +++ b/routers/repo/repo.go @@ -219,11 +219,17 @@ func Action(ctx *middleware.Context) { err = models.StarRepo(ctx.User.Id, ctx.Repo.Repository.Id, false) case "fork": repo, error := models.ForkRepository(ctx.User, ctx.Repo.Repository) - log.Info("Tried to fork a repo!") - log.Info("Repo thing is " + repo.Name) if error != nil { + log.Error(4, "Action(%s): %v", ctx.Params(":action"), error) + ctx.JSON(200, map[string]interface{}{ + "ok": false, + "err": error.Error(), + }) + return + } + if error == nil { + ctx.Redirect(setting.AppSubUrl + "/" + repo.Owner.Name + "/" + repo.Name) - ctx.Redirect(setting.AppSubUrl + "/" + ctx.User.Name + "/" + repo.Name) return } case "desc": From 29ac3980ffdb5faa525d77fddc109c9023ebe257 Mon Sep 17 00:00:00 2001 From: evolvedlight Date: Mon, 13 Oct 2014 20:23:30 +0100 Subject: [PATCH 3/3] More changes --- models/repo.go | 13 +++++++++++++ templates/repo/header.tmpl | 3 ++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/models/repo.go b/models/repo.go index 2019542102d9..0ca8b305eab5 100644 --- a/models/repo.go +++ b/models/repo.go @@ -178,6 +178,10 @@ func (repo *Repository) GetPath() string { return RepoPath(repo.Owner.Name, repo.Name) } +func (repo *Repository) IsOwnedBy(u *User) bool { + return repo.OwnerId == u.Id +} + // DescriptionHtml does special handles to description and return HTML string. func (repo *Repository) DescriptionHtml() template.HTML { sanitize := func(s string) string { @@ -932,6 +936,13 @@ func DeleteRepository(uid, repoId int64, userName string) error { sess.Rollback() return err } + + if repo.IsFork { + if _, err = sess.Exec("UPDATE `repository` SET num_forks = num_forks - 1 WHERE id = ?", repo.ForkId); err != nil { + sess.Rollback() + return err + } + } if _, err = sess.Exec("UPDATE `user` SET num_repos = num_repos - 1 WHERE id = ?", uid); err != nil { sess.Rollback() @@ -1249,6 +1260,8 @@ func ForkRepository(u *User, oldRepo *Repository) (*Repository, error) { LowerName: oldRepo.LowerName, Description: oldRepo.Description, IsPrivate: oldRepo.IsPrivate, + IsFork: true, + ForkId: oldRepo.Id, } if _, err = sess.Insert(repo); err != nil { diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index f0ebae5e6d05..884910d1c52d 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -45,12 +45,13 @@
  • - + +
  • @@ -104,6 +105,7 @@ {{if .RightIdx}}{{.RightIdx}}{{end}}
    {{ToUtf8 .Content}}