func GetDiffRange(repoPath, beforeCommitId string, afterCommitId string, maxlines int) (*Diff, error) { repo, err := git.OpenRepository(repoPath) if err != nil { return nil, err } commit, err := repo.GetCommit(afterCommitId) if err != nil { return nil, err } rd, wr := io.Pipe() var cmd *exec.Cmd // if "after" commit given if beforeCommitId == "" { // First commit of repository. if commit.ParentCount() == 0 { cmd = exec.Command("git", "show", afterCommitId) } else { c, _ := commit.Parent(0) cmd = exec.Command("git", "diff", c.Id.String(), afterCommitId) } } else { cmd = exec.Command("git", "diff", beforeCommitId, afterCommitId) } cmd.Dir = repoPath cmd.Stdout = wr cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr done := make(chan error) go func() { cmd.Start() done <- cmd.Wait() wr.Close() }() defer rd.Close() desc := fmt.Sprintf("GetDiffRange(%s)", repoPath) pid := process.Add(desc, cmd) go func() { // In case process became zombie. select { case <-time.After(5 * time.Minute): if errKill := process.Kill(pid); errKill != nil { log.Error(4, "git_diff.ParsePatch(Kill): %v", err) } <-done // return "", ErrExecTimeout.Error(), ErrExecTimeout case err = <-done: process.Remove(pid) } }() return ParsePatch(pid, maxlines, cmd, rd) }
// RepoRef handles repository reference name including those contain `/`. func RepoRef() macaron.Handler { return func(ctx *Context) { var ( refName string err error ) // For API calls. if ctx.Repo.GitRepo == nil { repoPath := models.RepoPath(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) gitRepo, err := git.OpenRepository(repoPath) if err != nil { ctx.Handle(500, "RepoRef Invalid repo "+repoPath, err) return } ctx.Repo.GitRepo = gitRepo } // Get default branch. if len(ctx.Params("*")) == 0 { refName = ctx.Repo.Repository.DefaultBranch if !ctx.Repo.GitRepo.IsBranchExist(refName) { brs, err := ctx.Repo.GitRepo.GetBranches() if err != nil { ctx.Handle(500, "GetBranches", err) return } refName = brs[0] } ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName) if err != nil { ctx.Handle(500, "GetCommitOfBranch", err) return } ctx.Repo.CommitId = ctx.Repo.Commit.Id.String() ctx.Repo.IsBranch = true } else { hasMatched := false parts := strings.Split(ctx.Params("*"), "/") for i, part := range parts { refName = strings.TrimPrefix(refName+"/"+part, "/") if ctx.Repo.GitRepo.IsBranchExist(refName) || ctx.Repo.GitRepo.IsTagExist(refName) { if i < len(parts)-1 { ctx.Repo.TreeName = strings.Join(parts[i+1:], "/") } hasMatched = true break } } if !hasMatched && len(parts[0]) == 40 { refName = parts[0] ctx.Repo.TreeName = strings.Join(parts[1:], "/") } if ctx.Repo.GitRepo.IsBranchExist(refName) { ctx.Repo.IsBranch = true ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfBranch(refName) if err != nil { ctx.Handle(500, "GetCommitOfBranch", err) return } ctx.Repo.CommitId = ctx.Repo.Commit.Id.String() } else if ctx.Repo.GitRepo.IsTagExist(refName) { ctx.Repo.IsTag = true ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommitOfTag(refName) if err != nil { ctx.Handle(500, "GetCommitOfTag", err) return } ctx.Repo.CommitId = ctx.Repo.Commit.Id.String() } else if len(refName) == 40 { ctx.Repo.IsCommit = true ctx.Repo.CommitId = refName ctx.Repo.Commit, err = ctx.Repo.GitRepo.GetCommit(refName) if err != nil { ctx.Handle(404, "GetCommit", nil) return } } else { ctx.Handle(404, "RepoRef invalid repo", fmt.Errorf("branch or tag not exist: %s", refName)) return } } ctx.Repo.BranchName = refName ctx.Data["BranchName"] = ctx.Repo.BranchName ctx.Data["CommitId"] = ctx.Repo.CommitId ctx.Data["IsBranch"] = ctx.Repo.IsBranch ctx.Data["IsTag"] = ctx.Repo.IsTag ctx.Data["IsCommit"] = ctx.Repo.IsCommit ctx.Repo.CommitsCount, err = ctx.Repo.Commit.CommitsCount() if err != nil { ctx.Handle(500, "CommitsCount", err) return } ctx.Data["CommitsCount"] = ctx.Repo.CommitsCount } }
func RepoAssignment(redirect bool, args ...bool) macaron.Handler { return func(ctx *Context) { var ( displayBare bool // To display bare page if it is a bare repo. ) if len(args) >= 1 { displayBare = args[0] } var ( u *models.User err error ) userName := ctx.Params(":username") repoName := ctx.Params(":reponame") refName := ctx.Params(":branchname") if len(refName) == 0 { refName = ctx.Params(":path") } // Check if the user is the same as the repository owner if ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) { u = ctx.User } else { u, err = models.GetUserByName(userName) if err != nil { if err == models.ErrUserNotExist { ctx.Handle(404, "GetUserByName", err) } else { ctx.Handle(500, "GetUserByName", err) } return } } ctx.Repo.Owner = u // Get repository. repo, err := models.GetRepositoryByName(u.Id, repoName) if err != nil { if models.IsErrRepoNotExist(err) { ctx.Handle(404, "GetRepositoryByName", err) } else { ctx.Handle(500, "GetRepositoryByName", err) } return } else if err = repo.GetOwner(); err != nil { ctx.Handle(500, "GetOwner", err) return } mode, err := models.AccessLevel(ctx.User, repo) if err != nil { ctx.Handle(500, "AccessLevel", err) return } ctx.Repo.AccessMode = mode // Check access. if ctx.Repo.AccessMode == models.ACCESS_MODE_NONE { ctx.Handle(404, "no access right", err) return } ctx.Data["HasAccess"] = true if repo.IsMirror { ctx.Repo.Mirror, err = models.GetMirror(repo.Id) if err != nil { ctx.Handle(500, "GetMirror", err) return } ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval } repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues repo.NumOpenMilestones = repo.NumMilestones - repo.NumClosedMilestones ctx.Repo.Repository = repo ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName)) if err != nil { ctx.Handle(500, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err) return } ctx.Repo.GitRepo = gitRepo ctx.Repo.RepoLink, err = repo.RepoLink() if err != nil { ctx.Handle(500, "RepoLink", err) return } ctx.Data["RepoLink"] = ctx.Repo.RepoLink tags, err := ctx.Repo.GitRepo.GetTags() if err != nil { ctx.Handle(500, "GetTags", err) return } ctx.Data["Tags"] = tags ctx.Repo.Repository.NumTags = len(tags) // Non-fork repository will not return error in this method. if err = repo.GetForkRepo(); err != nil { ctx.Handle(500, "GetForkRepo", err) return } ctx.Data["Title"] = u.Name + "/" + repo.Name ctx.Data["Repository"] = repo ctx.Data["Owner"] = ctx.Repo.Repository.Owner ctx.Data["IsRepositoryOwner"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_WRITE ctx.Data["IsRepositoryAdmin"] = ctx.Repo.AccessMode >= models.ACCESS_MODE_ADMIN ctx.Data["DisableSSH"] = setting.DisableSSH ctx.Repo.CloneLink, err = repo.CloneLink() if err != nil { ctx.Handle(500, "CloneLink", err) return } ctx.Data["CloneLink"] = ctx.Repo.CloneLink if ctx.Query("go-get") == "1" { ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", setting.Domain, u.LowerName, repo.LowerName) } // repo is bare and display enable if ctx.Repo.Repository.IsBare { log.Debug("Bare repository: %s", ctx.Repo.RepoLink) // NOTE: to prevent templating error ctx.Data["BranchName"] = "" if displayBare { ctx.HTML(200, "repo/bare") } return } if ctx.IsSigned { ctx.Data["IsWatchingRepo"] = models.IsWatching(ctx.User.Id, repo.Id) ctx.Data["IsStaringRepo"] = models.IsStaring(ctx.User.Id, repo.Id) } ctx.Data["TagName"] = ctx.Repo.TagName brs, err := ctx.Repo.GitRepo.GetBranches() if err != nil { ctx.Handle(500, "GetBranches", err) return } ctx.Data["Branches"] = brs ctx.Data["BrancheCount"] = len(brs) // If not branch selected, try default one. // If default branch doesn't exists, fall back to some other branch. if ctx.Repo.BranchName == "" { if ctx.Repo.Repository.DefaultBranch != "" && gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) { ctx.Repo.BranchName = ctx.Repo.Repository.DefaultBranch } else if len(brs) > 0 { ctx.Repo.BranchName = brs[0] } } ctx.Data["BranchName"] = ctx.Repo.BranchName ctx.Data["CommitId"] = ctx.Repo.CommitId } }
func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName string, userId int64) error { isNew := strings.HasPrefix(oldCommitId, "0000000") if isNew && strings.HasPrefix(newCommitId, "0000000") { return fmt.Errorf("old rev and new rev both 000000") } f := RepoPath(repoUserName, repoName) gitUpdate := exec.Command("git", "update-server-info") gitUpdate.Dir = f gitUpdate.Run() isDel := strings.HasPrefix(newCommitId, "0000000") if isDel { log.GitLogger.Info("del rev", refName, "from", userName+"/"+repoName+".git", "by", userId) return nil } repo, err := git.OpenRepository(f) if err != nil { return fmt.Errorf("runUpdate.Open repoId: %v", err) } ru, err := GetUserByName(repoUserName) if err != nil { return fmt.Errorf("runUpdate.GetUserByName: %v", err) } repos, err := GetRepositoryByName(ru.Id, repoName) if err != nil { return fmt.Errorf("runUpdate.GetRepositoryByName userId: %v", err) } // Push tags. if strings.HasPrefix(refName, "refs/tags/") { tagName := git.RefEndName(refName) tag, err := repo.GetTag(tagName) if err != nil { log.GitLogger.Fatal(4, "runUpdate.GetTag: %v", err) } var actEmail string if tag.Tagger != nil { actEmail = tag.Tagger.Email } else { cmt, err := tag.Commit() if err != nil { log.GitLogger.Fatal(4, "runUpdate.GetTag Commit: %v", err) } actEmail = cmt.Committer.Email } commit := &base.PushCommits{} if err = CommitRepoAction(userId, ru.Id, userName, actEmail, repos.Id, repoUserName, repoName, refName, commit, oldCommitId, newCommitId); err != nil { log.GitLogger.Fatal(4, "CommitRepoAction: %s/%s:%v", repoUserName, repoName, err) } return err } newCommit, err := repo.GetCommit(newCommitId) if err != nil { return fmt.Errorf("runUpdate GetCommit of newCommitId: %v", err) } // Push new branch. var l *list.List if isNew { l, err = newCommit.CommitsBefore() if err != nil { return fmt.Errorf("Find CommitsBefore erro: %v", err) } } else { l, err = newCommit.CommitsBeforeUntil(oldCommitId) if err != nil { return fmt.Errorf("Find CommitsBeforeUntil erro: %v", err) } } if err != nil { return fmt.Errorf("runUpdate.Commit repoId: %v", err) } // Push commits. commits := make([]*base.PushCommit, 0) var actEmail string for e := l.Front(); e != nil; e = e.Next() { commit := e.Value.(*git.Commit) if actEmail == "" { actEmail = commit.Committer.Email } commits = append(commits, &base.PushCommit{commit.Id.String(), commit.Message(), commit.Author.Email, commit.Author.Name}) if len(commits) >= MAX_COMMITS { break } } if err = CommitRepoAction(userId, ru.Id, userName, actEmail, repos.Id, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits, ""}, oldCommitId, newCommitId); err != nil { return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err) } return nil }