diff --git a/models/models.go b/models/models.go index 570df0c114..60959c60e9 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 a79c2491ce..34b7cd8352 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 5562a8400a..dac0c48b36 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 8e5efd146f..fa97073c6e 100644 --- a/templates/repo/diff.tmpl +++ b/templates/repo/diff.tmpl @@ -96,6 +96,7 @@
@@ -104,6 +105,7 @@ | {{if .RightIdx}}{{.RightIdx}}{{end}} | +
{{ToUtf8 .Content}} |
diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl
index 699e90461e..f0ebae5e6d 100644
--- a/templates/repo/header.tmpl
+++ b/templates/repo/header.tmpl
@@ -44,14 +44,14 @@
-
+
\ No newline at end of file