// initRepoCommit temporarily changes with work directory. func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { var stderr string if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "add", "--all"); err != nil { return err } if len(stderr) > 0 { log.Trace("stderr(1): %s", stderr) } if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", "Init commit"); err != nil { return err } if len(stderr) > 0 { log.Trace("stderr(2): %s", stderr) } if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "push", "origin", "master"); err != nil { return err } if len(stderr) > 0 { log.Trace("stderr(3): %s", stderr) } return nil }
// initRepoCommit temporarily changes with work directory. func initRepoCommit(tmpPath string, sig *git.Signature) (err error) { var stderr string if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "add", "--all"); err != nil { return errors.New("git add: " + stderr) } if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "commit", fmt.Sprintf("--author='%s <%s>'", sig.Name, sig.Email), "-m", "Init commit"); err != nil { return errors.New("git commit: " + stderr) } if _, stderr, err = com.ExecCmdDir(tmpPath, "git", "push", "origin", "master"); err != nil { return errors.New("git push: " + stderr) } return nil }
func (repo *Repository) getCommitIdOfRef(refpath string) (string, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--verify", refpath) if err != nil { return "", errors.New(stderr) } return strings.Split(stdout, " ")[0], nil }
func (repo *Repository) CreateTag(tagName, idStr string) error { _, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", tagName, idStr) if err != nil { return errors.New(stderr) } return nil }
// RemoveRemote removes a remote from repository. func (repo *Repository) RemoveRemote(name string) error { _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "remove", name) if err != nil { return fmt.Errorf("remove remote(%s): %v", name, concatenateError(err, stderr)) } return nil }
// AddRemote adds a remote to repository. func (repo *Repository) AddRemote(name, path string) error { _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", name, path) if err != nil { return fmt.Errorf("add remote(%s - %s): %v", name, path, concatenateError(err, stderr)) } return nil }
// CreateRelease creates a new release of repository. func CreateRelease(gitRepo *git.Repository, rel *Release) error { isExist, err := IsReleaseExist(rel.RepoId, rel.TagName) if err != nil { return err } else if isExist { return ErrReleaseAlreadyExist } if !gitRepo.IsTagExist(rel.TagName) { _, stderr, err := com.ExecCmdDir(gitRepo.Path, "git", "tag", rel.TagName, "-m", rel.Title) if err != nil { return errors.New(stderr) } } else { commit, err := gitRepo.GetCommitOfTag(rel.TagName) if err != nil { return err } rel.NumCommits, err = commit.CommitsCount() if err != nil { return err } } rel.LowerTagName = strings.ToLower(rel.TagName) _, err = orm.InsertOne(rel) return err }
func (repo *Repository) commitsCount(id sha1) (int, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", id.String()) if err != nil { return 0, errors.New(stderr) } return StrToInt(strings.TrimSpace(stdout)) }
// MigrateRepository migrates a existing repository from other project hosting. func MigrateRepository(user *User, name, desc string, private, mirror bool, url string) (*Repository, error) { repo, err := CreateRepository(user, name, desc, "", "", private, mirror, false) if err != nil { return nil, err } // Clone to temprory path and do the init commit. tmpDir := filepath.Join(os.TempDir(), fmt.Sprintf("%d", time.Now().Nanosecond())) os.MkdirAll(tmpDir, os.ModePerm) repoPath := RepoPath(user.Name, name) repo.IsBare = false if mirror { if err = MirrorRepository(repo.Id, user.Name, repo.Name, repoPath, url); err != nil { return repo, err } repo.IsMirror = true return repo, UpdateRepository(repo) } // Clone from local repository. _, stderr, err := com.ExecCmd("git", "clone", repoPath, tmpDir) if err != nil { return repo, err } else if strings.Contains(stderr, "fatal:") { return repo, errors.New("git clone: " + stderr) } // Pull data from source. _, stderr, err = com.ExecCmdDir(tmpDir, "git", "pull", url) if err != nil { return repo, err } else if strings.Contains(stderr, "fatal:") { return repo, errors.New("git pull: " + stderr) } // Push data to local repository. if _, stderr, err = com.ExecCmdDir(tmpDir, "git", "push", "origin", "master"); err != nil { return repo, err } else if strings.Contains(stderr, "fatal:") { return repo, errors.New("git push: " + stderr) } return repo, UpdateRepository(repo) }
// GetMergeBase checks and returns merge base of two branches. func (repo *Repository) GetMergeBase(remoteBranch, headBranch string) (string, error) { // Get merge base commit. stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch) if err != nil { return "", fmt.Errorf("get merge base: %v", concatenateError(err, stderr)) } return strings.TrimSpace(stdout), nil }
// GetTags returns all tags of given repository. func (repo *Repository) GetTags() ([]string, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l") if err != nil { return nil, errors.New(stderr) } tags := strings.Split(stdout, "\n") return tags[:len(tags)-1], nil }
func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "diff", "--name-only", startCommitID+"..."+endCommitID) if err != nil { return 0, fmt.Errorf("list changed files: %v", concatenateError(err, stderr)) } return len(strings.Split(stdout, "\n")) - 1, nil }
func (repo *Repository) getTagsReversed() ([]string, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l", "--sort=-v:refname") if err != nil { return nil, concatenateError(err, stderr) } tags := strings.Split(stdout, "\n") return tags[:len(tags)-1], nil }
func (repo *Repository) FileCommitsCount(branch, file string) (int, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", branch, "--", file) if err != nil { return 0, errors.New(stderr) } return com.StrTo(strings.TrimSpace(stdout)).Int() }
// Get last commit date from local repository func (g *githubPackage) LocalLastCommitDate() (time.Time, error) { stdout, _, _ := com.ExecCmdDir(g.Dir(), "git", "log", "-1", "--date=rfc2822", "--pretty=format:%cd") layout := "Mon, _2 Jan 2006 15:04:05 -0700" t, err := time.Parse(layout, stdout) if err != nil { return time.Time{}, errors.New("Error parse local time") } return t.UTC(), nil }
func (repo *Repository) getTree(id sha1) (*Tree, error) { treePath := filepathFromSHA1(repo.Path, id.String()) if !com.IsFile(treePath) { _, _, err := com.ExecCmdDir(repo.Path, "git", "ls-tree", id.String()) if err != nil { return nil, fmt.Errorf("repo.getTree: %v", ErrNotExist) } } return NewTree(repo, id), nil }
// GetTags returns all tags of given repository. func (repo *Repository) GetTags() ([]string, error) { if gitVer.AtLeast(MustParseVersion("2.0.0")) { return repo.getTagsReversed() } stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "tag", "-l") if err != nil { return nil, concatenateError(err, stderr) } tags := strings.Split(stdout, "\n") return tags[:len(tags)-1], nil }
// Git deployment action func (g *GitTask) Do(b *builder.Builder, ctx *builder.Context) error { gitDir := path.Join(ctx.DstDir, ".git") if !com.IsDir(gitDir) { return ErrGitNotRepo } var err error if err = g.readRepo(ctx.DstDir); err != nil { return err } if g.opt.Branch == "" { return ErrGitNoBranch } // add files if _, stderr, err := com.ExecCmdDir(ctx.DstDir, "git", []string{"add", "--all"}...); err != nil { log15.Error("Deploy.Git.Error", "error", stderr) return err } log15.Debug("Deploy.Git.[" + g.opt.Branch + "].AddFiles") // commit message message := gitMessageReplacer.Replace(g.opt.Message) if _, stderr, err := com.ExecCmdDir(ctx.DstDir, "git", []string{"commit", "-m", message}...); err != nil { log15.Error("Deploy.Git.Error", "error", stderr) return err } log15.Debug("Deploy.Git.[" + g.opt.Branch + "].Commit.'" + message + "'") // push to repo _, stderr, err := com.ExecCmdDir(ctx.DstDir, "git", []string{ "push", "--force", "origin", g.opt.Branch}...) if err != nil { log15.Error("Deploy.Git.Error", "error", stderr) if stderr != "" { return errors.New(stderr) } return err } log15.Debug("Deploy.Git.[" + g.opt.Branch + "].Push") return nil }
// GetPullRequestInfo generates and returns pull request information // between base and head branches of repositories. func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (*PullRequestInfo, error) { // Add a temporary remote. tmpRemote := com.ToStr(time.Now().UnixNano()) _, stderr, err := com.ExecCmdDir(repo.Path, "git", "remote", "add", "-f", tmpRemote, basePath) if err != nil { return nil, fmt.Errorf("add base as remote: %v", concatenateError(err, stderr)) } defer func() { com.ExecCmdDir(repo.Path, "git", "remote", "remove", tmpRemote) }() prInfo := new(PullRequestInfo) var stdout string remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch // Get merge base commit. stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "merge-base", remoteBranch, headBranch) if err != nil { return nil, fmt.Errorf("get merge base: %v", concatenateError(err, stderr)) } prInfo.MergeBase = strings.TrimSpace(stdout) stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "log", remoteBranch+"..."+headBranch, prettyLogFormat) if err != nil { return nil, fmt.Errorf("list diff logs: %v", concatenateError(err, stderr)) } prInfo.Commits, err = parsePrettyFormatLog(repo, []byte(stdout)) if err != nil { return nil, fmt.Errorf("parsePrettyFormatLog: %v", err) } // Count number of changed files. stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "diff", "--name-only", remoteBranch+"..."+headBranch) if err != nil { return nil, fmt.Errorf("list changed files: %v", concatenateError(err, stderr)) } prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1 return prInfo, nil }
func (repo *Repository) getCommitOfRelPath(id sha1, relPath string) (*Commit, error) { stdout, _, err := com.ExecCmdDir(repo.Path, "git", "log", "-1", prettyLogFormat, id.String(), "--", relPath) if err != nil { return nil, err } id, err = NewIdFromString(string(stdout)) if err != nil { return nil, err } return repo.getCommit(id) }
// GetPullRequestInfo generates and returns pull request information // between base and head branches of repositories. func (repo *Repository) GetPullRequestInfo(basePath, baseBranch, headBranch string) (_ *PullRequestInfo, err error) { // Add a temporary remote. tmpRemote := com.ToStr(time.Now().UnixNano()) if err = repo.AddRemote(tmpRemote, basePath); err != nil { return nil, fmt.Errorf("AddRemote: %v", err) } defer func() { repo.RemoveRemote(tmpRemote) }() remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch prInfo := new(PullRequestInfo) prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch) if err != nil { return nil, fmt.Errorf("GetMergeBase: %v", err) } stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "log", prInfo.MergeBase+"..."+headBranch, prettyLogFormat) if err != nil { return nil, fmt.Errorf("list diff logs: %v", concatenateError(err, stderr)) } prInfo.Commits, err = parsePrettyFormatLog(repo, []byte(stdout)) if err != nil { return nil, fmt.Errorf("parsePrettyFormatLog: %v", err) } // Count number of changed files. stdout, stderr, err = com.ExecCmdDir(repo.Path, "git", "diff", "--name-only", remoteBranch+"..."+headBranch) if err != nil { return nil, fmt.Errorf("list changed files: %v", concatenateError(err, stderr)) } prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1 return prInfo, nil }
// readRepo branch func (g *GitTask) readRepo(dest string) error { content, _, err := com.ExecCmdDir(dest, "git", []string{"branch"}...) if err != nil { return err } contentData := strings.Split(content, "\n") for _, cnt := range contentData { if strings.HasPrefix(cnt, "*") { cntData := strings.Split(cnt, " ") g.opt.Branch = cntData[len(cntData)-1] return nil } } return nil }
func (repo *Repository) commitsCount(id sha1) (int, error) { if gitVer.LessThan(MustParseVersion("1.8.0")) { stdout, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "log", "--pretty=format:''", id.String()) if err != nil { return 0, errors.New(string(stderr)) } return len(bytes.Split(stdout, []byte("\n"))), nil } stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "rev-list", "--count", id.String()) if err != nil { return 0, errors.New(stderr) } return com.StrTo(strings.TrimSpace(stdout)).Int() }
func (repo *Repository) GetBranches() ([]string, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--heads") if err != nil { return nil, concatenateError(err, stderr) } infos := strings.Split(stdout, "\n") branches := make([]string, len(infos)-1) for i, info := range infos[:len(infos)-1] { parts := strings.Split(info, " ") if len(parts) != 2 { continue // NOTE: I should believe git will not give me wrong string. } branches[i] = strings.TrimPrefix(parts[1], "refs/heads/") } return branches, nil }
func (c *Commit) CreateArchive(path string, archiveType ArchiveType) error { var format string switch archiveType { case ZIP: format = "zip" case TARGZ: format = "tar.gz" default: return fmt.Errorf("unknown format: %v", archiveType) } _, stderr, err := com.ExecCmdDir(c.repo.Path, "git", "archive", "--format="+format, "-o", path, c.ID.String()) if err != nil { return fmt.Errorf("%s", stderr) } return nil }
func (repo *Repository) getTag(id sha1) (*Tag, error) { if repo.tagCache != nil { if t, ok := repo.tagCache[id]; ok { return t, nil } } else { repo.tagCache = make(map[sha1]*Tag, 10) } // Get tag type. tp, stderr, err := com.ExecCmdDir(repo.Path, "git", "cat-file", "-t", id.String()) if err != nil { return nil, errors.New(stderr) } tp = strings.TrimSpace(tp) // Tag is a commit. if ObjectType(tp) == COMMIT { tag := &Tag{ Id: id, Object: id, Type: string(COMMIT), repo: repo, } repo.tagCache[id] = tag return tag, nil } // Tag with message. data, bytErr, err := com.ExecCmdDirBytes(repo.Path, "git", "cat-file", "-p", id.String()) if err != nil { return nil, errors.New(string(bytErr)) } tag, err := parseTagData(data) if err != nil { return nil, err } tag.Id = id tag.repo = repo repo.tagCache[id] = tag return tag, nil }
func (te *TreeEntry) Size() int64 { if te.IsDir() { return 0 } if te.sized { return te.size } stdout, _, err := com.ExecCmdDir(te.ptree.repo.Path, "git", "cat-file", "-s", te.Id.String()) if err != nil { return 0 } te.sized = true te.size = com.StrTo(strings.TrimSpace(stdout)).MustInt64() return te.size }
// GetTag returns a Git tag by given name. func (repo *Repository) GetTag(tagName string) (*Tag, error) { stdout, stderr, err := com.ExecCmdDir(repo.Path, "git", "show-ref", "--tags", tagName) if err != nil { return nil, errors.New(stderr) } id, err := NewIdFromString(strings.Split(stdout, " ")[0]) if err != nil { return nil, err } tag, err := repo.getTag(id) if err != nil { return nil, err } tag.Name = tagName return tag, nil }
func ReloadDocs() error { tocLocker.Lock() defer tocLocker.Unlock() localRoot := setting.Docs.Target // Fetch docs from remote. if setting.Docs.Type.IsRemote() { localRoot = docsRoot absRoot, err := filepath.Abs(localRoot) if err != nil { return fmt.Errorf("filepath.Abs: %v", err) } // Clone new or pull to update. if com.IsDir(absRoot) { stdout, stderr, err := com.ExecCmdDir(absRoot, "git", "pull") if err != nil { return fmt.Errorf("Fail to update docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr) } fmt.Println(stdout) } else { os.MkdirAll(filepath.Dir(absRoot), os.ModePerm) stdout, stderr, err := com.ExecCmd("git", "clone", setting.Docs.Target, absRoot) if err != nil { return fmt.Errorf("Fail to clone docs from remote source(%s): %v - %s", setting.Docs.Target, err, stderr) } fmt.Println(stdout) } } if !com.IsDir(localRoot) { return fmt.Errorf("Documentation not found: %s - %s", setting.Docs.Type, localRoot) } tocs, err := initToc(localRoot) if err != nil { return fmt.Errorf("initToc: %v", err) } initDocs(tocs, localRoot) Tocs = tocs return reloadProtects(localRoot) }
// GetPatch generates and returns patch data between given branches. func (repo *Repository) GetPatch(basePath, baseBranch, headBranch string) ([]byte, error) { // Add a temporary remote. tmpRemote := com.ToStr(time.Now().UnixNano()) _, stderr, err := com.ExecCmdDirBytes(repo.Path, "git", "remote", "add", "-f", tmpRemote, basePath) if err != nil { return nil, fmt.Errorf("add base as remote: %v", concatenateError(err, string(stderr))) } defer func() { com.ExecCmdDir(repo.Path, "git", "remote", "remove", tmpRemote) }() var stdout []byte remoteBranch := "remotes/" + tmpRemote + "/" + baseBranch stdout, stderr, err = com.ExecCmdDirBytes(repo.Path, "git", "diff", "-p", remoteBranch, headBranch) if err != nil { return nil, concatenateError(err, string(stderr)) } return stdout, nil }