// NewRepo is a constructor for a repo object, parsing the tags that exist func NewRepo(repoPath, branch string) (*GitRepo, error) { if branch == "" { return nil, fmt.Errorf("must specify a branch") } log.Println("Opening repo at ", repoPath+"/.git") repo, err := git.OpenRepository(repoPath + "/.git") if err != nil { return nil, err } r := &GitRepo{ repo: repo, branch: branch, } err = r.parseTags() if err != nil { return nil, err } if err := r.calcVersion(); err != nil { return nil, err } return r, nil }
func GetDiff(repoPath, commitid string) (*Diff, error) { repo, err := git.OpenRepository(repoPath) if err != nil { return nil, err } commit, err := repo.GetCommit(commitid) if err != nil { return nil, err } rd, wr := io.Pipe() var cmd *exec.Cmd // First commit of repository. if commit.ParentCount() == 0 { cmd = exec.Command("git", "show", commitid) } else { c, _ := commit.Parent(0) cmd = exec.Command("git", "diff", c.Id.String(), commitid) } cmd.Dir = repoPath cmd.Stdout = wr cmd.Stdin = os.Stdin cmd.Stderr = os.Stderr go func() { cmd.Run() wr.Close() }() defer rd.Close() return ParsePatch(cmd, rd) }
func IsBranchExist(userName, repoName, branchName string) bool { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return false } return repo.IsBranchExist(branchName) }
func GetCommit(userName, repoName, commitId string) (*git.Commit, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } return repo.GetCommit(commitId) }
func GetDiffRange(repoPath, beforeCommitId string, afterCommitId string) (*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, cmd, rd) }
// GetCommitsByCommitId returns all commits of given commitId of repository. func GetCommitsByCommitId(userName, repoName, commitId string) (*list.List, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } oid, err := git.NewOidFromString(commitId) if err != nil { return nil, err } return repo.CommitsBefore(oid) }
// GetCommitsByBranch returns all commits of given branch of repository. func GetCommitsByBranch(userName, repoName, branchName string) (*list.List, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } r, err := repo.LookupReference(fmt.Sprintf("refs/heads/%s", branchName)) if err != nil { return nil, err } return r.AllCommits() }
func newRepo(t *testing.T) GitRepo { path := createTestRepo(t) repo, err := git.OpenRepository(path) checkFatal(t, err) seedTestRepo(t, repo) r, err := NewRepo(repo.Path, "master") if err != nil { t.Fatal("Error creating repo", err) } return *r }
// adds a #major comit to the repo func newRepoMajor(t *testing.T) GitRepo { tr := createTestRepo(t) repo, err := git.OpenRepository(tr) checkFatal(t, err) seedTestRepo(t, repo) updateReadme(t, repo, "#major change") r, err := NewRepo(repo.Path, "master") if err != nil { t.Fatal("Error creating repo", err) } return *r }
func GetTargetFile(userName, repoName, branchName, commitId, rpath string) (*RepoFile, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } commit, err := repo.GetCommitOfBranch(branchName) if err != nil { commit, err = repo.GetCommit(commitId) if err != nil { return nil, err } } parts := strings.Split(path.Clean(rpath), "/") var entry *git.TreeEntry tree := commit.Tree for i, part := range parts { if i == len(parts)-1 { entry = tree.EntryByName(part) if entry == nil { return nil, ErrRepoFileNotExist } } else { tree, err = repo.SubTree(tree, part) if err != nil { return nil, err } } } size, err := repo.ObjectSize(entry.Id) if err != nil { return nil, err } repoFile := &RepoFile{ entry, rpath, size, repo, commit, } return repoFile, nil }
// GetBranches returns all branches of given repository. func GetBranches(userName, repoName string) ([]string, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } refs, err := repo.AllReferences() if err != nil { return nil, err } brs := make([]string, len(refs)) for i, ref := range refs { brs[i] = ref.BranchName() } return brs, nil }
// GetTags returns all tags of given repository. func GetTags(userName, repoName string) ([]string, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } refs, err := repo.AllTags() if err != nil { return nil, err } tags := make([]string, len(refs)) for i, ref := range refs { tags[i] = ref.Name } return tags, nil }
// for command: ./gogs update func runUpdate(c *cli.Context) { execDir, _ := base.ExecDir() newLogger(execDir) base.NewConfigContext() models.LoadModelsConfig() if models.UseSQLite3 { os.Chdir(execDir) } models.SetEngine() args := c.Args() if len(args) != 3 { log.Error("received less 3 parameters") return } refName := args[0] if refName == "" { log.Error("refName is empty, shouldn't use") return } oldCommitId := args[1] newCommitId := args[2] isNew := strings.HasPrefix(oldCommitId, "0000000") if isNew && strings.HasPrefix(newCommitId, "0000000") { log.Error("old rev and new rev both 000000") return } userName := os.Getenv("userName") userId := os.Getenv("userId") //repoId := os.Getenv("repoId") repoName := os.Getenv("repoName") f := models.RepoPath(userName, repoName) gitUpdate := exec.Command("git", "update-server-info") gitUpdate.Dir = f gitUpdate.Run() repo, err := git.OpenRepository(f) if err != nil { log.Error("runUpdate.Open repoId: %v", err) return } newOid, err := git.NewOidFromString(newCommitId) if err != nil { log.Error("runUpdate.Ref repoId: %v", err) return } newCommit, err := repo.LookupCommit(newOid) if err != nil { log.Error("runUpdate.Ref repoId: %v", err) return } var l *list.List // if a new branch if isNew { l, err = repo.CommitsBefore(newCommit.Id()) if err != nil { log.Error("Find CommitsBefore erro:", err) return } } else { oldOid, err := git.NewOidFromString(oldCommitId) if err != nil { log.Error("runUpdate.Ref repoId: %v", err) return } oldCommit, err := repo.LookupCommit(oldOid) if err != nil { log.Error("runUpdate.Ref repoId: %v", err) return } l = repo.CommitsBetween(newCommit, oldCommit) } if err != nil { log.Error("runUpdate.Commit repoId: %v", err) return } sUserId, err := strconv.Atoi(userId) if err != nil { log.Error("runUpdate.Parse userId: %v", err) return } repos, err := models.GetRepositoryByName(int64(sUserId), repoName) if err != nil { log.Error("runUpdate.GetRepositoryByName userId: %v", err) return } commits := make([]*base.PushCommit, 0) var maxCommits = 3 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) >= maxCommits { break } } //commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()}) if err = models.CommitRepoAction(int64(sUserId), userName, actEmail, repos.Id, repoName, git.BranchName(refName), &base.PushCommits{l.Len(), commits}); err != nil { log.Error("runUpdate.models.CommitRepoAction: %v", err) } }
func RepoAssignment(redirect bool, args ...bool) martini.Handler { return func(ctx *Context, params martini.Params) { // valid brachname var validBranch bool // display bare quick start if it is a bare repo var displayBare bool if len(args) >= 1 { validBranch = args[0] } if len(args) >= 2 { displayBare = args[1] } var ( user *models.User err error ) userName := params["username"] repoName := params["reponame"] branchName := params["branchname"] // get repository owner ctx.Repo.IsOwner = ctx.IsSigned && ctx.User.LowerName == strings.ToLower(userName) if !ctx.Repo.IsOwner { user, err = models.GetUserByName(params["username"]) if err != nil { if redirect { ctx.Redirect("/") return } ctx.Handle(200, "RepoAssignment", err) return } } else { user = ctx.User } if user == nil { if redirect { ctx.Redirect("/") return } ctx.Handle(200, "RepoAssignment", errors.New("invliad user account for single repository")) return } // get repository repo, err := models.GetRepositoryByName(user.Id, repoName) if err != nil { if err == models.ErrRepoNotExist { ctx.Handle(404, "RepoAssignment", err) } else if redirect { ctx.Redirect("/") return } ctx.Handle(404, "RepoAssignment", err) return } ctx.Repo.Repository = repo ctx.Data["IsBareRepo"] = ctx.Repo.Repository.IsBare gitRepo, err := git.OpenRepository(models.RepoPath(userName, repoName)) if err != nil { ctx.Handle(404, "RepoAssignment Invalid repo "+models.RepoPath(userName, repoName), err) return } ctx.Repo.GitRepo = gitRepo ctx.Repo.Owner = user ctx.Repo.RepoLink = "/" + user.Name + "/" + repo.Name ctx.Data["Title"] = user.Name + "/" + repo.Name ctx.Data["Repository"] = repo ctx.Data["Owner"] = user ctx.Data["RepoLink"] = ctx.Repo.RepoLink ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner ctx.Data["BranchName"] = "" ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", base.RunUser, base.Domain, user.LowerName, repo.LowerName) ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", base.AppUrl, user.LowerName, repo.LowerName) ctx.Data["CloneLink"] = ctx.Repo.CloneLink // when repo is bare, not valid branch if !ctx.Repo.Repository.IsBare && validBranch { detect: if len(branchName) > 0 { // TODO check tag if models.IsBranchExist(user.Name, repoName, branchName) { ctx.Repo.IsBranch = true ctx.Repo.BranchName = branchName ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(branchName) if err != nil { ctx.Handle(404, "RepoAssignment invalid branch", nil) return } ctx.Repo.CommitId = ctx.Repo.Commit.Oid.String() } else if len(branchName) == 40 { ctx.Repo.IsCommit = true ctx.Repo.CommitId = branchName ctx.Repo.BranchName = branchName ctx.Repo.Commit, err = gitRepo.GetCommit(branchName) if err != nil { ctx.Handle(404, "RepoAssignment invalid commit", nil) return } } else { ctx.Handle(404, "RepoAssignment invalid repo", nil) return } } else { branchName = "master" goto detect } ctx.Data["IsBranch"] = ctx.Repo.IsBranch ctx.Data["IsCommit"] = ctx.Repo.IsCommit } // repo is bare and display enable if displayBare && ctx.Repo.Repository.IsBare { ctx.HTML(200, "repo/single_bare") return } if ctx.IsSigned { ctx.Repo.IsWatching = models.IsWatching(ctx.User.Id, repo.Id) } ctx.Data["BranchName"] = ctx.Repo.BranchName ctx.Data["CommitId"] = ctx.Repo.CommitId ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching } }
func RepoAssignment(redirect bool, args ...bool) martini.Handler { return func(ctx *Context, params martini.Params) { log.Trace(fmt.Sprint(args)) // valid brachname var validBranch bool // display bare quick start if it is a bare repo var displayBare bool if len(args) >= 1 { // Note: argument has wrong value in Go1.3 martini. // validBranch = args[0] validBranch = true } if len(args) >= 2 { // displayBare = args[1] displayBare = true } var ( user *models.User err error isTrueOwner bool ) userName := params["username"] repoName := params["reponame"] refName := params["branchname"] // Collaborators who have write access can be seen as owners. if ctx.IsSigned { ctx.Repo.IsOwner, err = models.HasAccess(ctx.User.Name, userName+"/"+repoName, models.AU_WRITABLE) if err != nil { ctx.Handle(500, "RepoAssignment(HasAccess)", err) return } isTrueOwner = ctx.User.LowerName == strings.ToLower(userName) } if !isTrueOwner { user, err = models.GetUserByName(userName) if err != nil { if err == models.ErrUserNotExist { ctx.Handle(404, "RepoAssignment(GetUserByName)", err) return } else if redirect { ctx.Redirect("/") return } ctx.Handle(500, "RepoAssignment(GetUserByName)", err) return } } else { user = ctx.User } if user == nil { if redirect { ctx.Redirect("/") return } ctx.Handle(403, "RepoAssignment", errors.New("invliad user account for single repository")) return } ctx.Repo.Owner = user // get repository repo, err := models.GetRepositoryByName(user.Id, repoName) if err != nil { if err == models.ErrRepoNotExist { ctx.Handle(404, "RepoAssignment", err) return } else if redirect { ctx.Redirect("/") return } ctx.Handle(500, "RepoAssignment", err) return } // Check access. if repo.IsPrivate && !ctx.Repo.IsOwner { if ctx.User == nil { ctx.Handle(404, "RepoAssignment(HasAccess)", nil) return } hasAccess, err := models.HasAccess(ctx.User.Name, ctx.Repo.Owner.Name+"/"+repo.Name, models.AU_READABLE) if err != nil { ctx.Handle(500, "RepoAssignment(HasAccess)", err) return } else if !hasAccess { ctx.Handle(404, "RepoAssignment(HasAccess)", nil) return } } ctx.Repo.HasAccess = true ctx.Data["HasAccess"] = true if repo.IsMirror { ctx.Repo.Mirror, err = models.GetMirror(repo.Id) if err != nil { ctx.Handle(500, "RepoAssignment(GetMirror)", err) return } ctx.Data["MirrorInterval"] = ctx.Repo.Mirror.Interval } repo.NumOpenIssues = repo.NumIssues - repo.NumClosedIssues 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 = "/" + user.Name + "/" + repo.Name tags, err := ctx.Repo.GitRepo.GetTags() if err != nil { ctx.Handle(500, "RepoAssignment(GetTags))", err) return } ctx.Repo.Repository.NumTags = len(tags) ctx.Data["Title"] = user.Name + "/" + repo.Name ctx.Data["Repository"] = repo ctx.Data["Owner"] = user ctx.Data["RepoLink"] = ctx.Repo.RepoLink ctx.Data["IsRepositoryOwner"] = ctx.Repo.IsOwner ctx.Data["BranchName"] = "" if base.SshPort != 22 { ctx.Repo.CloneLink.SSH = fmt.Sprintf("ssh://%s@%s/%s/%s.git", base.RunUser, base.Domain, user.LowerName, repo.LowerName) } else { ctx.Repo.CloneLink.SSH = fmt.Sprintf("%s@%s:%s/%s.git", base.RunUser, base.Domain, user.LowerName, repo.LowerName) } ctx.Repo.CloneLink.HTTPS = fmt.Sprintf("%s%s/%s.git", base.AppUrl, user.LowerName, repo.LowerName) ctx.Data["CloneLink"] = ctx.Repo.CloneLink if ctx.Repo.Repository.IsGoget { ctx.Data["GoGetLink"] = fmt.Sprintf("%s%s/%s", base.AppUrl, user.LowerName, repo.LowerName) ctx.Data["GoGetImport"] = fmt.Sprintf("%s/%s/%s", base.Domain, user.LowerName, repo.LowerName) } // when repo is bare, not valid branch if !ctx.Repo.Repository.IsBare && validBranch { detect: if len(refName) > 0 { if gitRepo.IsBranchExist(refName) { ctx.Repo.IsBranch = true ctx.Repo.BranchName = refName ctx.Repo.Commit, err = gitRepo.GetCommitOfBranch(refName) if err != nil { ctx.Handle(404, "RepoAssignment invalid branch", nil) return } ctx.Repo.CommitId = ctx.Repo.Commit.Id.String() } else if gitRepo.IsTagExist(refName) { ctx.Repo.IsBranch = true ctx.Repo.BranchName = refName ctx.Repo.Commit, err = gitRepo.GetCommitOfTag(refName) if err != nil { ctx.Handle(404, "RepoAssignment invalid tag", nil) return } ctx.Repo.CommitId = ctx.Repo.Commit.Id.String() } else if len(refName) == 40 { ctx.Repo.IsCommit = true ctx.Repo.CommitId = refName ctx.Repo.BranchName = refName ctx.Repo.Commit, err = gitRepo.GetCommit(refName) if err != nil { ctx.Handle(404, "RepoAssignment invalid commit", nil) return } } else { ctx.Handle(404, "RepoAssignment invalid repo", nil) return } } else { if len(refName) == 0 { if gitRepo.IsBranchExist(ctx.Repo.Repository.DefaultBranch) { refName = ctx.Repo.Repository.DefaultBranch } else { brs, err := gitRepo.GetBranches() if err != nil { ctx.Handle(500, "RepoAssignment(GetBranches))", err) return } refName = brs[0] } } goto detect } ctx.Data["IsBranch"] = ctx.Repo.IsBranch ctx.Data["IsCommit"] = ctx.Repo.IsCommit log.Debug("Repo.Commit: %v", ctx.Repo.Commit) } log.Debug("displayBare: %v; IsBare: %v", displayBare, ctx.Repo.Repository.IsBare) // repo is bare and display enable if displayBare && ctx.Repo.Repository.IsBare { log.Debug("Bare repository: %s", ctx.Repo.RepoLink) ctx.HTML(200, "repo/single_bare") return } if ctx.IsSigned { ctx.Repo.IsWatching = models.IsWatching(ctx.User.Id, repo.Id) } ctx.Data["BranchName"] = ctx.Repo.BranchName brs, err := ctx.Repo.GitRepo.GetBranches() if err != nil { log.Error("RepoAssignment(GetBranches): %v", err) } ctx.Data["Branches"] = brs ctx.Data["CommitId"] = ctx.Repo.CommitId ctx.Data["IsRepositoryWatching"] = ctx.Repo.IsWatching } }
func runServ(k *cli.Context) { base.NewConfigContext() models.LoadModelsConfig() models.NewEngine() keys := strings.Split(os.Args[2], "-") if len(keys) != 2 { fmt.Println("auth file format error") return } keyId, err := strconv.ParseInt(keys[1], 10, 64) if err != nil { fmt.Println("auth file format error") return } user, err := models.GetUserByKeyId(keyId) if err != nil { fmt.Println("You have no right to access") return } cmd := os.Getenv("SSH_ORIGINAL_COMMAND") if cmd == "" { println("Hi", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.") return } verb, args := parseCmd(cmd) rRepo := strings.Trim(args, "'") rr := strings.SplitN(rRepo, "/", 2) if len(rr) != 2 { println("Unavilable repository", args) return } repoName := rr[1] if strings.HasSuffix(repoName, ".git") { repoName = repoName[:len(repoName)-4] } repo, err := models.GetRepositoryByName(user.Id, repoName) var isExist bool = true if err != nil { if err == models.ErrRepoNotExist { isExist = false } else { println("Unavilable repository", err) return } } isWrite := In(verb, COMMANDS_WRITE) isRead := In(verb, COMMANDS_READONLY) switch { case isWrite: has, err := models.HasAccess(user.Name, repoName, models.AU_WRITABLE) if err != nil { println("Inernel error:", err) return } if !has { println("You have no right to write this repository") return } case isRead: has, err := models.HasAccess(user.Name, repoName, models.AU_READABLE) if err != nil { println("Inernel error") return } if !has { has, err = models.HasAccess(user.Name, repoName, models.AU_WRITABLE) if err != nil { println("Inernel error") return } } if !has { println("You have no right to access this repository") return } default: println("Unknown command") return } if !isExist { if isRead { println("Repository", user.Name+"/"+repoName, "is not exist") return } else if isWrite { _, err := models.CreateRepository(user, repoName, "", "", "", false, true) if err != nil { println("Create repository failed") return } } } rep, err := git.OpenRepository(models.RepoPath(user.Name, repoName)) if err != nil { println(err.Error()) return } refs, err := rep.AllReferencesMap() if err != nil { println(err.Error()) return } gitcmd := exec.Command(verb, rRepo) gitcmd.Dir = base.RepoRootPath var s string b := bytes.NewBufferString(s) gitcmd.Stdout = io.MultiWriter(os.Stdout, b) //gitcmd.Stdin = io.MultiReader(os.Stdin, b) gitcmd.Stdin = os.Stdin gitcmd.Stderr = os.Stderr if err = gitcmd.Run(); err != nil { println("execute command error:", err.Error()) } if !strings.HasPrefix(cmd, "git-receive-pack") { return } // update //w, _ := os.Create("serve.log") //defer w.Close() //log.SetOutput(w) var t = "ok refs/heads/" var i int var refname string for { l, err := b.ReadString('\n') if err != nil { break } i = i + 1 l = l[:len(l)-1] idx := strings.Index(l, t) if idx > 0 { refname = l[idx+len(t):] } } var ref *git.Reference var ok bool var l *list.List //log.Info("----", refname, "-----") if ref, ok = refs[refname]; !ok { refs, err = rep.AllReferencesMap() if err != nil { println(err.Error()) return } if ref, ok = refs[refname]; !ok { println("unknow reference name -", refname, "-") return } l, err = ref.AllCommits() if err != nil { println(err.Error()) return } } else { //log.Info("----", ref, "-----") var last *git.Commit //log.Info("00000", ref.Oid.String()) last, err = ref.LastCommit() if err != nil { println(err.Error()) return } ref2, err := rep.LookupReference(ref.Name) if err != nil { println(err.Error()) return } //log.Info("11111", ref2.Oid.String()) before, err := ref2.LastCommit() if err != nil { println(err.Error()) return } //log.Info("----", before.Id(), "-----", last.Id()) l = ref.CommitsBetween(before, last) } commits := make([][]string, 0) var maxCommits = 3 for e := l.Front(); e != nil; e = e.Next() { commit := e.Value.(*git.Commit) commits = append(commits, []string{commit.Id().String(), commit.Message()}) if len(commits) >= maxCommits { break } } if err = models.CommitRepoAction(user.Id, user.Name, repo.Id, repoName, refname, &base.PushCommits{l.Len(), commits}); err != nil { log.Error("runUpdate.models.CommitRepoAction: %v", err, commits) } else { //log.Info("refname", refname) //log.Info("Listen: %v", cmd) //fmt.Println("...", cmd) //runUpdate(k) c := exec.Command("git", "update-server-info") c.Dir = models.RepoPath(user.Name, repoName) err := c.Run() if err != nil { log.Error("update-server-info: %v", err) } } }
func Update(refName, oldCommitId, newCommitId, userName, repoName string, userId int64) { isNew := strings.HasPrefix(oldCommitId, "0000000") if isNew && strings.HasPrefix(newCommitId, "0000000") { qlog.Fatal("old rev and new rev both 000000") } f := RepoPath(userName, repoName) gitUpdate := exec.Command("git", "update-server-info") gitUpdate.Dir = f gitUpdate.Run() repo, err := git.OpenRepository(f) if err != nil { qlog.Fatalf("runUpdate.Open repoId: %v", err) } newCommit, err := repo.GetCommit(newCommitId) if err != nil { qlog.Fatalf("runUpdate GetCommit of newCommitId: %v", err) return } var l *list.List // if a new branch if isNew { l, err = newCommit.CommitsBefore() if err != nil { qlog.Fatalf("Find CommitsBefore erro: %v", err) } } else { l, err = newCommit.CommitsBeforeUntil(oldCommitId) if err != nil { qlog.Fatalf("Find CommitsBeforeUntil erro: %v", err) return } } if err != nil { qlog.Fatalf("runUpdate.Commit repoId: %v", err) } repos, err := GetRepositoryByName(userId, repoName) if err != nil { qlog.Fatalf("runUpdate.GetRepositoryByName userId: %v", err) } commits := make([]*base.PushCommit, 0) var maxCommits = 3 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) >= maxCommits { break } } //commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()}) if err = CommitRepoAction(userId, userName, actEmail, repos.Id, repoName, refName, &base.PushCommits{l.Len(), commits}); err != nil { qlog.Fatalf("runUpdate.models.CommitRepoAction: %v", err) } }
func Update(refName, oldCommitId, newCommitId, userName, repoUserName, repoName string, userId int64) error { //fmt.Println(refName, oldCommitId, newCommitId) //fmt.Println(userName, repoUserName, repoName) 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) } // if tags push if strings.HasPrefix(refName, "refs/tags/") { tagName := git.RefEndName(refName) tag, err := repo.GetTag(tagName) if err != nil { log.GitLogger.Fatal("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("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); err != nil { log.GitLogger.Fatal("runUpdate.models.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) } var l *list.List // if a new branch 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) } // if commits push commits := make([]*base.PushCommit, 0) var maxCommits = 3 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) >= maxCommits { break } } //commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()}) if err = CommitRepoAction(userId, ru.Id, userName, actEmail, repos.Id, repoUserName, repoName, refName, &base.PushCommits{l.Len(), commits}); err != nil { return fmt.Errorf("runUpdate.models.CommitRepoAction: %s/%s:%v", repoUserName, repoName, err) } return nil }
func getReposFiles(userName, repoName, commitId string, rpath string) ([]*RepoFile, error) { repo, err := git.OpenRepository(RepoPath(userName, repoName)) if err != nil { return nil, err } commit, err := repo.GetCommit(commitId) if err != nil { return nil, err } var repodirs []*RepoFile var repofiles []*RepoFile commit.Tree.Walk(func(dirname string, entry *git.TreeEntry) int { if dirname == rpath { // TODO: size get method shoule be improved size, err := repo.ObjectSize(entry.Id) if err != nil { return 0 } var cm = commit var i int for { i = i + 1 //fmt.Println(".....", i, cm.Id(), cm.ParentCount()) if cm.ParentCount() == 0 { break } else if cm.ParentCount() == 1 { pt, _ := repo.SubTree(cm.Parent(0).Tree, dirname) if pt == nil { break } pEntry := pt.EntryByName(entry.Name) if pEntry == nil || !pEntry.Id.Equal(entry.Id) { break } else { cm = cm.Parent(0) } } else { var emptyCnt = 0 var sameIdcnt = 0 var lastSameCm *git.Commit //fmt.Println(".....", cm.ParentCount()) for i := 0; i < cm.ParentCount(); i++ { //fmt.Println("parent", i, cm.Parent(i).Id()) p := cm.Parent(i) pt, _ := repo.SubTree(p.Tree, dirname) var pEntry *git.TreeEntry if pt != nil { pEntry = pt.EntryByName(entry.Name) } //fmt.Println("pEntry", pEntry) if pEntry == nil { emptyCnt = emptyCnt + 1 if emptyCnt+sameIdcnt == cm.ParentCount() { if lastSameCm == nil { goto loop } else { cm = lastSameCm break } } } else { //fmt.Println(i, "pEntry", pEntry.Id, "entry", entry.Id) if !pEntry.Id.Equal(entry.Id) { goto loop } else { lastSameCm = cm.Parent(i) sameIdcnt = sameIdcnt + 1 if emptyCnt+sameIdcnt == cm.ParentCount() { // TODO: now follow the first parent commit? cm = lastSameCm //fmt.Println("sameId...") break } } } } } } loop: rp := &RepoFile{ entry, path.Join(dirname, entry.Name), size, repo, cm, } if entry.IsFile() { repofiles = append(repofiles, rp) } else if entry.IsDir() { repodirs = append(repodirs, rp) } } return 0 }) return append(repodirs, repofiles...), nil }