@@ -1,503 +0,0 @@ | |||
// Copyright 2014 The Gogs Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package models | |||
import ( | |||
"bufio" | |||
"bytes" | |||
"container/list" | |||
"errors" | |||
"fmt" | |||
"io" | |||
"os" | |||
"os/exec" | |||
"path" | |||
"strings" | |||
"github.com/Unknwon/com" | |||
"github.com/gogits/git" | |||
"github.com/gogits/gogs/modules/base" | |||
"github.com/gogits/gogs/modules/log" | |||
) | |||
// RepoFile represents a file object in git repository. | |||
type RepoFile struct { | |||
*git.TreeEntry | |||
Path string | |||
Size int64 | |||
Repo *git.Repository | |||
Commit *git.Commit | |||
} | |||
// LookupBlob returns the content of an object. | |||
func (file *RepoFile) LookupBlob() (*git.Blob, error) { | |||
if file.Repo == nil { | |||
return nil, ErrRepoFileNotLoaded | |||
} | |||
return file.Repo.LookupBlob(file.Id) | |||
} | |||
// 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 | |||
} | |||
func IsBranchExist(userName, repoName, branchName string) bool { | |||
repo, err := git.OpenRepository(RepoPath(userName, repoName)) | |||
if err != nil { | |||
return false | |||
} | |||
return repo.IsBranchExist(branchName) | |||
} | |||
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 | |||
} | |||
// GetReposFiles returns a list of file object in given directory of repository. | |||
// func GetReposFilesOfBranch(userName, repoName, branchName, rpath string) ([]*RepoFile, error) { | |||
// return getReposFiles(userName, repoName, commitId, rpath) | |||
// } | |||
// GetReposFiles returns a list of file object in given directory of repository. | |||
func GetReposFiles(userName, repoName, commitId, rpath string) ([]*RepoFile, error) { | |||
return getReposFiles(userName, repoName, commitId, rpath) | |||
} | |||
func getReposFiles(userName, repoName, commitId string, rpath string) ([]*RepoFile, error) { | |||
repopath := RepoPath(userName, repoName) | |||
repo, err := git.OpenRepository(repopath) | |||
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 | |||
} | |||
stdout, _, err := com.ExecCmdDir(repopath, "git", "log", "-1", "--pretty=format:%H", commitId, "--", path.Join(dirname, entry.Name)) | |||
if err != nil { | |||
return 0 | |||
} | |||
filecm, err := repo.GetCommit(string(stdout)) | |||
if err != nil { | |||
return 0 | |||
} | |||
rp := &RepoFile{ | |||
entry, | |||
path.Join(dirname, entry.Name), | |||
size, | |||
repo, | |||
filecm, | |||
} | |||
if entry.IsFile() { | |||
repofiles = append(repofiles, rp) | |||
} else if entry.IsDir() { | |||
repodirs = append(repodirs, rp) | |||
} | |||
} | |||
return 0 | |||
}) | |||
return append(repodirs, repofiles...), nil | |||
} | |||
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) | |||
} | |||
// 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() | |||
} | |||
// 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) | |||
} | |||
// Diff line types. | |||
const ( | |||
DIFF_LINE_PLAIN = iota + 1 | |||
DIFF_LINE_ADD | |||
DIFF_LINE_DEL | |||
DIFF_LINE_SECTION | |||
) | |||
const ( | |||
DIFF_FILE_ADD = iota + 1 | |||
DIFF_FILE_CHANGE | |||
DIFF_FILE_DEL | |||
) | |||
type DiffLine struct { | |||
LeftIdx int | |||
RightIdx int | |||
Type int | |||
Content string | |||
} | |||
func (d DiffLine) GetType() int { | |||
return d.Type | |||
} | |||
type DiffSection struct { | |||
Name string | |||
Lines []*DiffLine | |||
} | |||
type DiffFile struct { | |||
Name string | |||
Addition, Deletion int | |||
Type int | |||
Sections []*DiffSection | |||
} | |||
type Diff struct { | |||
TotalAddition, TotalDeletion int | |||
Files []*DiffFile | |||
} | |||
func (diff *Diff) NumFiles() int { | |||
return len(diff.Files) | |||
} | |||
const DIFF_HEAD = "diff --git " | |||
func ParsePatch(reader io.Reader) (*Diff, error) { | |||
scanner := bufio.NewScanner(reader) | |||
var ( | |||
curFile *DiffFile | |||
curSection = &DiffSection{ | |||
Lines: make([]*DiffLine, 0, 10), | |||
} | |||
leftLine, rightLine int | |||
) | |||
diff := &Diff{Files: make([]*DiffFile, 0)} | |||
var i int | |||
for scanner.Scan() { | |||
line := scanner.Text() | |||
// fmt.Println(i, line) | |||
if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") { | |||
continue | |||
} | |||
i = i + 1 | |||
// Diff data too large. | |||
if i == 5000 { | |||
log.Warn("Diff data too large") | |||
return &Diff{}, nil | |||
} | |||
if line == "" { | |||
continue | |||
} | |||
if line[0] == ' ' { | |||
diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line, LeftIdx: leftLine, RightIdx: rightLine} | |||
leftLine++ | |||
rightLine++ | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
continue | |||
} else if line[0] == '@' { | |||
curSection = &DiffSection{} | |||
curFile.Sections = append(curFile.Sections, curSection) | |||
ss := strings.Split(line, "@@") | |||
diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: line} | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
// Parse line number. | |||
ranges := strings.Split(ss[len(ss)-2][1:], " ") | |||
leftLine, _ = base.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int() | |||
rightLine, _ = base.StrTo(strings.Split(ranges[1], ",")[0]).Int() | |||
continue | |||
} else if line[0] == '+' { | |||
curFile.Addition++ | |||
diff.TotalAddition++ | |||
diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line, RightIdx: rightLine} | |||
rightLine++ | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
continue | |||
} else if line[0] == '-' { | |||
curFile.Deletion++ | |||
diff.TotalDeletion++ | |||
diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line, LeftIdx: leftLine} | |||
if leftLine > 0 { | |||
leftLine++ | |||
} | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
continue | |||
} | |||
// Get new file. | |||
if strings.HasPrefix(line, DIFF_HEAD) { | |||
fs := strings.Split(line[len(DIFF_HEAD):], " ") | |||
a := fs[0] | |||
curFile = &DiffFile{ | |||
Name: a[strings.Index(a, "/")+1:], | |||
Type: DIFF_FILE_CHANGE, | |||
Sections: make([]*DiffSection, 0, 10), | |||
} | |||
diff.Files = append(diff.Files, curFile) | |||
// Check file diff type. | |||
for scanner.Scan() { | |||
switch { | |||
case strings.HasPrefix(scanner.Text(), "new file"): | |||
curFile.Type = DIFF_FILE_ADD | |||
case strings.HasPrefix(scanner.Text(), "deleted"): | |||
curFile.Type = DIFF_FILE_DEL | |||
case strings.HasPrefix(scanner.Text(), "index"): | |||
curFile.Type = DIFF_FILE_CHANGE | |||
} | |||
if curFile.Type > 0 { | |||
break | |||
} | |||
} | |||
} | |||
} | |||
return diff, 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 | |||
} | |||
// First commit of repository. | |||
if commit.ParentCount() == 0 { | |||
rd, wr := io.Pipe() | |||
go func() { | |||
cmd := exec.Command("git", "show", commitid) | |||
cmd.Dir = repoPath | |||
cmd.Stdout = wr | |||
cmd.Stdin = os.Stdin | |||
cmd.Stderr = os.Stderr | |||
cmd.Run() | |||
wr.Close() | |||
}() | |||
defer rd.Close() | |||
return ParsePatch(rd) | |||
} | |||
rd, wr := io.Pipe() | |||
go func() { | |||
cmd := exec.Command("git", "diff", commit.Parent(0).Oid.String(), commitid) | |||
cmd.Dir = repoPath | |||
cmd.Stdout = wr | |||
cmd.Stdin = os.Stdin | |||
cmd.Stderr = os.Stderr | |||
cmd.Run() | |||
wr.Close() | |||
}() | |||
defer rd.Close() | |||
return ParsePatch(rd) | |||
} | |||
const prettyLogFormat = `--pretty=format:%H%n%an <%ae> %at%n%s` | |||
func parsePrettyFormatLog(logByts []byte) (*list.List, error) { | |||
l := list.New() | |||
buf := bytes.NewBuffer(logByts) | |||
if buf.Len() == 0 { | |||
return l, nil | |||
} | |||
idx := 0 | |||
var commit *git.Commit | |||
for { | |||
line, err := buf.ReadString('\n') | |||
if err != nil && err != io.EOF { | |||
return nil, err | |||
} | |||
line = strings.TrimSpace(line) | |||
// fmt.Println(line) | |||
var parseErr error | |||
switch idx { | |||
case 0: // SHA1. | |||
commit = &git.Commit{} | |||
commit.Oid, parseErr = git.NewOidFromString(line) | |||
case 1: // Signature. | |||
commit.Author, parseErr = git.NewSignatureFromCommitline([]byte(line + " ")) | |||
case 2: // Commit message. | |||
commit.CommitMessage = line | |||
l.PushBack(commit) | |||
idx = -1 | |||
} | |||
if parseErr != nil { | |||
return nil, parseErr | |||
} | |||
idx++ | |||
if err == io.EOF { | |||
break | |||
} | |||
} | |||
return l, nil | |||
} | |||
// SearchCommits searches commits in given branch and keyword of repository. | |||
func SearchCommits(repoPath, branch, keyword string) (*list.List, error) { | |||
stdout, stderr, err := com.ExecCmdDirBytes(repoPath, "git", "log", branch, "-100", | |||
"-i", "--grep="+keyword, prettyLogFormat) | |||
if err != nil { | |||
return nil, err | |||
} else if len(stderr) > 0 { | |||
return nil, errors.New(string(stderr)) | |||
} | |||
return parsePrettyFormatLog(stdout) | |||
} | |||
// GetCommitsByRange returns certain number of commits with given page of repository. | |||
func GetCommitsByRange(repoPath, branch string, page int) (*list.List, error) { | |||
stdout, stderr, err := com.ExecCmdDirBytes(repoPath, "git", "log", branch, | |||
"--skip="+base.ToStr((page-1)*50), "--max-count=50", prettyLogFormat) | |||
if err != nil { | |||
return nil, err | |||
} else if len(stderr) > 0 { | |||
return nil, errors.New(string(stderr)) | |||
} | |||
return parsePrettyFormatLog(stdout) | |||
} | |||
// GetCommitsCount returns the commits count of given branch of repository. | |||
func GetCommitsCount(repoPath, branch string) (int, error) { | |||
stdout, stderr, err := com.ExecCmdDir(repoPath, "git", "rev-list", "--count", branch) | |||
if err != nil { | |||
return 0, err | |||
} else if len(stderr) > 0 { | |||
return 0, errors.New(stderr) | |||
} | |||
return base.StrTo(strings.TrimSpace(stdout)).Int() | |||
} |
@@ -0,0 +1,207 @@ | |||
// Copyright 2014 The Gogs Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package models | |||
import ( | |||
"bufio" | |||
"io" | |||
"os" | |||
"os/exec" | |||
"strings" | |||
"github.com/gogits/git" | |||
"github.com/gogits/gogs/modules/base" | |||
"github.com/gogits/gogs/modules/log" | |||
) | |||
// Diff line types. | |||
const ( | |||
DIFF_LINE_PLAIN = iota + 1 | |||
DIFF_LINE_ADD | |||
DIFF_LINE_DEL | |||
DIFF_LINE_SECTION | |||
) | |||
const ( | |||
DIFF_FILE_ADD = iota + 1 | |||
DIFF_FILE_CHANGE | |||
DIFF_FILE_DEL | |||
) | |||
type DiffLine struct { | |||
LeftIdx int | |||
RightIdx int | |||
Type int | |||
Content string | |||
} | |||
func (d DiffLine) GetType() int { | |||
return d.Type | |||
} | |||
type DiffSection struct { | |||
Name string | |||
Lines []*DiffLine | |||
} | |||
type DiffFile struct { | |||
Name string | |||
Addition, Deletion int | |||
Type int | |||
Sections []*DiffSection | |||
} | |||
type Diff struct { | |||
TotalAddition, TotalDeletion int | |||
Files []*DiffFile | |||
} | |||
func (diff *Diff) NumFiles() int { | |||
return len(diff.Files) | |||
} | |||
const DIFF_HEAD = "diff --git " | |||
func ParsePatch(reader io.Reader) (*Diff, error) { | |||
scanner := bufio.NewScanner(reader) | |||
var ( | |||
curFile *DiffFile | |||
curSection = &DiffSection{ | |||
Lines: make([]*DiffLine, 0, 10), | |||
} | |||
leftLine, rightLine int | |||
) | |||
diff := &Diff{Files: make([]*DiffFile, 0)} | |||
var i int | |||
for scanner.Scan() { | |||
line := scanner.Text() | |||
// fmt.Println(i, line) | |||
if strings.HasPrefix(line, "+++ ") || strings.HasPrefix(line, "--- ") { | |||
continue | |||
} | |||
i = i + 1 | |||
// Diff data too large. | |||
if i == 5000 { | |||
log.Warn("Diff data too large") | |||
return &Diff{}, nil | |||
} | |||
if line == "" { | |||
continue | |||
} | |||
if line[0] == ' ' { | |||
diffLine := &DiffLine{Type: DIFF_LINE_PLAIN, Content: line, LeftIdx: leftLine, RightIdx: rightLine} | |||
leftLine++ | |||
rightLine++ | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
continue | |||
} else if line[0] == '@' { | |||
curSection = &DiffSection{} | |||
curFile.Sections = append(curFile.Sections, curSection) | |||
ss := strings.Split(line, "@@") | |||
diffLine := &DiffLine{Type: DIFF_LINE_SECTION, Content: line} | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
// Parse line number. | |||
ranges := strings.Split(ss[len(ss)-2][1:], " ") | |||
leftLine, _ = base.StrTo(strings.Split(ranges[0], ",")[0][1:]).Int() | |||
rightLine, _ = base.StrTo(strings.Split(ranges[1], ",")[0]).Int() | |||
continue | |||
} else if line[0] == '+' { | |||
curFile.Addition++ | |||
diff.TotalAddition++ | |||
diffLine := &DiffLine{Type: DIFF_LINE_ADD, Content: line, RightIdx: rightLine} | |||
rightLine++ | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
continue | |||
} else if line[0] == '-' { | |||
curFile.Deletion++ | |||
diff.TotalDeletion++ | |||
diffLine := &DiffLine{Type: DIFF_LINE_DEL, Content: line, LeftIdx: leftLine} | |||
if leftLine > 0 { | |||
leftLine++ | |||
} | |||
curSection.Lines = append(curSection.Lines, diffLine) | |||
continue | |||
} | |||
// Get new file. | |||
if strings.HasPrefix(line, DIFF_HEAD) { | |||
fs := strings.Split(line[len(DIFF_HEAD):], " ") | |||
a := fs[0] | |||
curFile = &DiffFile{ | |||
Name: a[strings.Index(a, "/")+1:], | |||
Type: DIFF_FILE_CHANGE, | |||
Sections: make([]*DiffSection, 0, 10), | |||
} | |||
diff.Files = append(diff.Files, curFile) | |||
// Check file diff type. | |||
for scanner.Scan() { | |||
switch { | |||
case strings.HasPrefix(scanner.Text(), "new file"): | |||
curFile.Type = DIFF_FILE_ADD | |||
case strings.HasPrefix(scanner.Text(), "deleted"): | |||
curFile.Type = DIFF_FILE_DEL | |||
case strings.HasPrefix(scanner.Text(), "index"): | |||
curFile.Type = DIFF_FILE_CHANGE | |||
} | |||
if curFile.Type > 0 { | |||
break | |||
} | |||
} | |||
} | |||
} | |||
return diff, 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 | |||
} | |||
// First commit of repository. | |||
if commit.ParentCount() == 0 { | |||
rd, wr := io.Pipe() | |||
go func() { | |||
cmd := exec.Command("git", "show", commitid) | |||
cmd.Dir = repoPath | |||
cmd.Stdout = wr | |||
cmd.Stdin = os.Stdin | |||
cmd.Stderr = os.Stderr | |||
cmd.Run() | |||
wr.Close() | |||
}() | |||
defer rd.Close() | |||
return ParsePatch(rd) | |||
} | |||
rd, wr := io.Pipe() | |||
go func() { | |||
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 | |||
cmd.Run() | |||
wr.Close() | |||
}() | |||
defer rd.Close() | |||
return ParsePatch(rd) | |||
} |
@@ -28,34 +28,25 @@ func Update(refName, oldCommitId, newCommitId, userName, repoName string, userId | |||
qlog.Fatalf("runUpdate.Open repoId: %v", err) | |||
} | |||
newOid, err := git.NewOidFromString(newCommitId) | |||
newCommit, err := repo.GetCommit(newCommitId) | |||
if err != nil { | |||
qlog.Fatalf("runUpdate.Ref repoId:%v err: %v", newCommitId, err) | |||
} | |||
newCommit, err := repo.LookupCommit(newOid) | |||
if err != nil { | |||
qlog.Fatalf("runUpdate.Ref repoId: %v", err) | |||
qlog.Fatalf("runUpdate GetCommit of newCommitId: %v", err) | |||
return | |||
} | |||
var l *list.List | |||
// if a new branch | |||
if isNew { | |||
l, err = repo.CommitsBefore(newCommit.Id()) | |||
l, err = newCommit.CommitsBefore() | |||
if err != nil { | |||
qlog.Fatalf("Find CommitsBefore erro:", err) | |||
} | |||
} else { | |||
oldOid, err := git.NewOidFromString(oldCommitId) | |||
if err != nil { | |||
qlog.Fatalf("runUpdate.Ref repoId: %v", err) | |||
} | |||
oldCommit, err := repo.LookupCommit(oldOid) | |||
l, err = newCommit.CommitsBeforeUntil(oldCommitId) | |||
if err != nil { | |||
qlog.Fatalf("runUpdate.Ref repoId: %v", err) | |||
qlog.Fatalf("Find CommitsBeforeUntil erro:", err) | |||
return | |||
} | |||
l = repo.CommitsBetween(newCommit, oldCommit) | |||
} | |||
if err != nil { | |||
@@ -76,7 +67,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoName string, userId | |||
actEmail = commit.Committer.Email | |||
} | |||
commits = append(commits, | |||
&base.PushCommit{commit.Id().String(), | |||
&base.PushCommit{commit.Id.String(), | |||
commit.Message(), | |||
commit.Author.Email, | |||
commit.Author.Name}) | |||
@@ -87,7 +78,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoName string, userId | |||
//commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()}) | |||
if err = CommitRepoAction(userId, userName, actEmail, | |||
repos.Id, repoName, git.BranchName(refName), &base.PushCommits{l.Len(), commits}); err != nil { | |||
repos.Id, repoName, git.RefEndName(refName), &base.PushCommits{l.Len(), commits}); err != nil { | |||
qlog.Fatalf("runUpdate.models.CommitRepoAction: %v", err) | |||
} | |||
} |
@@ -131,7 +131,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler { | |||
detect: | |||
if len(branchName) > 0 { | |||
// TODO check tag | |||
if models.IsBranchExist(user.Name, repoName, branchName) { | |||
if gitRepo.IsBranchExist(branchName) { | |||
ctx.Repo.IsBranch = true | |||
ctx.Repo.BranchName = branchName | |||
@@ -141,7 +141,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler { | |||
return | |||
} | |||
ctx.Repo.CommitId = ctx.Repo.Commit.Oid.String() | |||
ctx.Repo.CommitId = ctx.Repo.Commit.Id.String() | |||
} else if len(branchName) == 40 { | |||
ctx.Repo.IsCommit = true | |||
@@ -181,7 +181,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler { | |||
} | |||
ctx.Data["BranchName"] = ctx.Repo.BranchName | |||
brs, err := models.GetBranches(user.Name, repoName) | |||
brs, err := ctx.Repo.GitRepo.GetBranches() | |||
if err != nil { | |||
log.Error("RepoAssignment(GetBranches): %v", err) | |||
} |
@@ -1,32 +0,0 @@ | |||
// Copyright 2014 The Gogs Authors. All rights reserved. | |||
// Use of this source code is governed by a MIT-style | |||
// license that can be found in the LICENSE file. | |||
package v1 | |||
import ( | |||
"github.com/gogits/gogs/models" | |||
"github.com/gogits/gogs/modules/middleware" | |||
) | |||
func SearchCommits(ctx *middleware.Context) { | |||
userName := ctx.Query("username") | |||
repoName := ctx.Query("reponame") | |||
branch := ctx.Query("branch") | |||
keyword := ctx.Query("q") | |||
if len(keyword) == 0 { | |||
ctx.Render.JSON(404, nil) | |||
return | |||
} | |||
commits, err := models.SearchCommits(models.RepoPath(userName, repoName), branch, keyword) | |||
if err != nil { | |||
ctx.Render.JSON(200, map[string]interface{}{"ok": false}) | |||
return | |||
} | |||
ctx.Render.JSON(200, map[string]interface{}{ | |||
"ok": true, | |||
"commits": commits, | |||
}) | |||
} |
@@ -7,12 +7,11 @@ package repo | |||
import ( | |||
"github.com/go-martini/martini" | |||
"github.com/gogits/gogs/models" | |||
"github.com/gogits/gogs/modules/middleware" | |||
) | |||
func Branches(ctx *middleware.Context, params martini.Params) { | |||
brs, err := models.GetBranches(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) | |||
brs, err := ctx.Repo.GitRepo.GetBranches() | |||
if err != nil { | |||
ctx.Handle(404, "repo.Branches", err) | |||
return |
@@ -5,7 +5,6 @@ | |||
package repo | |||
import ( | |||
"container/list" | |||
"path" | |||
"github.com/go-martini/martini" | |||
@@ -16,11 +15,10 @@ import ( | |||
) | |||
func Commits(ctx *middleware.Context, params martini.Params) { | |||
userName := params["username"] | |||
repoName := params["reponame"] | |||
branchName := params["branchname"] | |||
userName := ctx.Repo.Owner.Name | |||
repoName := ctx.Repo.Repository.Name | |||
brs, err := models.GetBranches(userName, repoName) | |||
brs, err := ctx.Repo.GitRepo.GetBranches() | |||
if err != nil { | |||
ctx.Handle(500, "repo.Commits", err) | |||
return | |||
@@ -29,8 +27,7 @@ func Commits(ctx *middleware.Context, params martini.Params) { | |||
return | |||
} | |||
repoPath := models.RepoPath(userName, repoName) | |||
commitsCount, err := models.GetCommitsCount(repoPath, branchName) | |||
commitsCount, err := ctx.Repo.Commit.CommitsCount() | |||
if err != nil { | |||
ctx.Handle(500, "repo.Commits(GetCommitsCount)", err) | |||
return | |||
@@ -51,7 +48,7 @@ func Commits(ctx *middleware.Context, params martini.Params) { | |||
} | |||
//both `git log branchName` and `git log commitId` work | |||
commits, err := models.GetCommitsByRange(repoPath, branchName, page) | |||
commits, err := ctx.Repo.Commit.CommitsByRange(page) | |||
if err != nil { | |||
ctx.Handle(500, "repo.Commits(get commits)", err) | |||
return | |||
@@ -70,7 +67,6 @@ func Commits(ctx *middleware.Context, params martini.Params) { | |||
func Diff(ctx *middleware.Context, params martini.Params) { | |||
userName := ctx.Repo.Owner.Name | |||
repoName := ctx.Repo.Repository.Name | |||
branchName := ctx.Repo.BranchName | |||
commitId := ctx.Repo.CommitId | |||
commit := ctx.Repo.Commit | |||
@@ -82,19 +78,15 @@ func Diff(ctx *middleware.Context, params martini.Params) { | |||
} | |||
isImageFile := func(name string) bool { | |||
repoFile, err := models.GetTargetFile(userName, repoName, | |||
branchName, commitId, name) | |||
blob, err := ctx.Repo.Commit.GetBlobByPath(name) | |||
if err != nil { | |||
return false | |||
} | |||
blob, err := repoFile.LookupBlob() | |||
data, err := blob.Data() | |||
if err != nil { | |||
return false | |||
} | |||
data := blob.Contents() | |||
_, isImage := base.IsImageFile(data) | |||
return isImage | |||
} | |||
@@ -119,9 +111,8 @@ func SearchCommits(ctx *middleware.Context, params martini.Params) { | |||
userName := params["username"] | |||
repoName := params["reponame"] | |||
branchName := params["branchname"] | |||
brs, err := models.GetBranches(userName, repoName) | |||
brs, err := ctx.Repo.GitRepo.GetBranches() | |||
if err != nil { | |||
ctx.Handle(500, "repo.SearchCommits(GetBranches)", err) | |||
return | |||
@@ -130,11 +121,8 @@ func SearchCommits(ctx *middleware.Context, params martini.Params) { | |||
return | |||
} | |||
var commits *list.List | |||
if !models.IsBranchExist(userName, repoName, branchName) { | |||
ctx.Handle(404, "repo.SearchCommits(IsBranchExist)", err) | |||
return | |||
} else if commits, err = models.SearchCommits(models.RepoPath(userName, repoName), branchName, keyword); err != nil { | |||
commits, err := ctx.Repo.Commit.SearchCommits(keyword) | |||
if err != nil { | |||
ctx.Handle(500, "repo.SearchCommits(SearchCommits)", err) | |||
return | |||
} |
@@ -5,7 +5,6 @@ | |||
package repo | |||
import ( | |||
"github.com/gogits/gogs/models" | |||
"github.com/gogits/gogs/modules/middleware" | |||
) | |||
@@ -13,7 +12,7 @@ func Releases(ctx *middleware.Context) { | |||
ctx.Data["Title"] = "Releases" | |||
ctx.Data["IsRepoToolbarReleases"] = true | |||
ctx.Data["IsRepoReleaseNew"] = false | |||
tags, err := models.GetTags(ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) | |||
tags, err := ctx.Repo.GitRepo.GetTags() | |||
if err != nil { | |||
ctx.Handle(404, "repo.Releases(GetTags)", err) | |||
return |
@@ -8,6 +8,7 @@ import ( | |||
"encoding/base64" | |||
"errors" | |||
"fmt" | |||
"github.com/gogits/git" | |||
"path" | |||
"path/filepath" | |||
"strings" | |||
@@ -107,7 +108,6 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) { | |||
func Single(ctx *middleware.Context, params martini.Params) { | |||
branchName := ctx.Repo.BranchName | |||
commitId := ctx.Repo.CommitId | |||
userName := ctx.Repo.Owner.Name | |||
repoName := ctx.Repo.Repository.Name | |||
@@ -125,46 +125,42 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
ctx.Data["IsRepoToolbarSource"] = true | |||
// Branches. | |||
brs, err := models.GetBranches(userName, repoName) | |||
if err != nil { | |||
ctx.Handle(404, "repo.Single(GetBranches)", err) | |||
return | |||
} | |||
ctx.Data["Branches"] = brs | |||
isViewBranch := ctx.Repo.IsBranch | |||
ctx.Data["IsViewBranch"] = isViewBranch | |||
repoFile, err := models.GetTargetFile(userName, repoName, | |||
branchName, commitId, treename) | |||
treePath := treename | |||
if len(treePath) != 0 { | |||
treePath = treePath + "/" | |||
} | |||
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treename) | |||
if err != nil && err != models.ErrRepoFileNotExist { | |||
ctx.Handle(404, "repo.Single(GetTargetFile)", err) | |||
if err != nil && err != git.ErrNotExist { | |||
ctx.Handle(404, "repo.Single(GetTreeEntryByPath)", err) | |||
return | |||
} | |||
if len(treename) != 0 && repoFile == nil { | |||
if len(treename) != 0 && entry == nil { | |||
ctx.Handle(404, "repo.Single", nil) | |||
return | |||
} | |||
if repoFile != nil && repoFile.IsFile() { | |||
if blob, err := repoFile.LookupBlob(); err != nil { | |||
ctx.Handle(404, "repo.Single(repoFile.LookupBlob)", err) | |||
if entry != nil && entry.IsFile() { | |||
blob := entry.Blob() | |||
if data, err := blob.Data(); err != nil { | |||
ctx.Handle(404, "repo.Single(blob.Data)", err) | |||
} else { | |||
ctx.Data["FileSize"] = repoFile.Size | |||
ctx.Data["FileSize"] = blob.Size() | |||
ctx.Data["IsFile"] = true | |||
ctx.Data["FileName"] = repoFile.Name | |||
ext := path.Ext(repoFile.Name) | |||
ctx.Data["FileName"] = blob.Name | |||
ext := path.Ext(blob.Name) | |||
if len(ext) > 0 { | |||
ext = ext[1:] | |||
} | |||
ctx.Data["FileExt"] = ext | |||
ctx.Data["FileLink"] = rawLink + "/" + treename | |||
data := blob.Contents() | |||
_, isTextFile := base.IsTextFile(data) | |||
_, isImageFile := base.IsImageFile(data) | |||
ctx.Data["FileIsText"] = isTextFile | |||
@@ -172,7 +168,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
if isImageFile { | |||
ctx.Data["IsImageFile"] = true | |||
} else { | |||
readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name) | |||
readmeExist := base.IsMarkdownFile(blob.Name) || base.IsReadmeFile(blob.Name) | |||
ctx.Data["ReadmeExist"] = readmeExist | |||
if readmeExist { | |||
ctx.Data["FileContent"] = string(base.RenderMarkdown(data, "")) | |||
@@ -186,21 +182,35 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
} else { | |||
// Directory and file list. | |||
files, err := models.GetReposFiles(userName, repoName, ctx.Repo.CommitId, treename) | |||
tree, err := ctx.Repo.Commit.SubTree(treename) | |||
if err != nil { | |||
ctx.Handle(404, "repo.Single(GetReposFiles)", err) | |||
ctx.Handle(404, "repo.Single(SubTree)", err) | |||
return | |||
} | |||
entries := tree.ListEntries() | |||
entries.Sort() | |||
files := make([][]interface{}, 0, len(entries)) | |||
for _, te := range entries { | |||
c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name)) | |||
if err != nil { | |||
ctx.Handle(404, "repo.Single(SubTree)", err) | |||
return | |||
} | |||
files = append(files, []interface{}{te, c}) | |||
} | |||
ctx.Data["Files"] = files | |||
var readmeFile *models.RepoFile | |||
var readmeFile *git.Blob | |||
for _, f := range files { | |||
for _, f := range entries { | |||
if !f.IsFile() || !base.IsReadmeFile(f.Name) { | |||
continue | |||
} else { | |||
readmeFile = f | |||
readmeFile = f.Blob() | |||
break | |||
} | |||
} | |||
@@ -208,13 +218,12 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
if readmeFile != nil { | |||
ctx.Data["ReadmeInSingle"] = true | |||
ctx.Data["ReadmeExist"] = true | |||
if blob, err := readmeFile.LookupBlob(); err != nil { | |||
if data, err := readmeFile.Data(); err != nil { | |||
ctx.Handle(404, "repo.Single(readmeFile.LookupBlob)", err) | |||
return | |||
} else { | |||
ctx.Data["FileSize"] = readmeFile.Size | |||
ctx.Data["FileLink"] = rawLink + "/" + treename | |||
data := blob.Contents() | |||
_, isTextFile := base.IsTextFile(data) | |||
ctx.Data["FileIsText"] = isTextFile | |||
ctx.Data["FileName"] = readmeFile.Name | |||
@@ -246,6 +255,7 @@ func Single(ctx *middleware.Context, params martini.Params) { | |||
ctx.Data["LastCommit"] = ctx.Repo.Commit | |||
ctx.Data["Paths"] = Paths | |||
ctx.Data["Treenames"] = treenames | |||
ctx.Data["TreePath"] = treePath | |||
ctx.Data["BranchLink"] = branchLink | |||
ctx.HTML(200, "repo/single") | |||
} | |||
@@ -254,31 +264,18 @@ func SingleDownload(ctx *middleware.Context, params martini.Params) { | |||
// Get tree path | |||
treename := params["_1"] | |||
branchName := params["branchname"] | |||
userName := params["username"] | |||
repoName := params["reponame"] | |||
var commitId string | |||
if !models.IsBranchExist(userName, repoName, branchName) { | |||
commitId = branchName | |||
branchName = "" | |||
} | |||
repoFile, err := models.GetTargetFile(userName, repoName, | |||
branchName, commitId, treename) | |||
blob, err := ctx.Repo.Commit.GetBlobByPath(treename) | |||
if err != nil { | |||
ctx.Handle(404, "repo.SingleDownload(GetTargetFile)", err) | |||
ctx.Handle(404, "repo.SingleDownload(GetBlobByPath)", err) | |||
return | |||
} | |||
blob, err := repoFile.LookupBlob() | |||
data, err := blob.Data() | |||
if err != nil { | |||
ctx.Handle(404, "repo.SingleDownload(LookupBlob)", err) | |||
ctx.Handle(404, "repo.SingleDownload(Data)", err) | |||
return | |||
} | |||
data := blob.Contents() | |||
contentType, isTextFile := base.IsTextFile(data) | |||
_, isImageFile := base.IsImageFile(data) | |||
ctx.Res.Header().Set("Content-Type", contentType) | |||
@@ -361,7 +358,8 @@ func SettingPost(ctx *middleware.Context) { | |||
} | |||
br := ctx.Query("branch") | |||
if models.IsBranchExist(ctx.User.Name, ctx.Repo.Repository.Name, br) { | |||
if git.IsBranchExist(models.RepoPath(ctx.User.Name, ctx.Repo.Repository.Name), br) { | |||
ctx.Repo.Repository.DefaultBranch = br | |||
} | |||
ctx.Repo.Repository.Description = ctx.Query("desc") |
@@ -1,6 +1,6 @@ | |||
<div class="panel panel-default info-box"> | |||
<div class="panel-heading info-head"> | |||
<a href="/{{.Username}}/{{.Reponame}}/commit/{{.LastCommit.Oid.String}}">{{.LastCommit.Message}}</a> | |||
<a href="/{{.Username}}/{{.Reponame}}/commit/{{.LastCommit.Id}}">{{.LastCommit.Message}}</a> | |||
</div> | |||
<div class="panel-body info-content"> | |||
<a href="/user/{{.LastCommit.Author.Name}}">{{.LastCommit.Author.Name}}</a> <span class="text-muted">{{TimeSince .LastCommit.Author.When}}</span> | |||
@@ -15,40 +15,37 @@ | |||
</tr> | |||
</thead> | |||
<tbody> | |||
{{if .HasParentPath}} | |||
<tr class="has-parent"> | |||
<td class="icon"><a href="{{.BranchLink}}{{.ParentPath}}"><i class="fa fa-reply"></i></a></td> | |||
<td class="name"><a href="{{.BranchLink}}{{.ParentPath}}">..</a></td> | |||
<td class="text"></td> | |||
<td class="date"></td> | |||
</tr> | |||
{{end}} | |||
{{range .Files}} | |||
<tr | |||
{{if .IsDir}}class="is-dir"{{end}}> | |||
<td class="icon"> | |||
<i class="fa {{if .IsDir}}fa-folder{{else}}fa-file-text-o{{end}}"></i> | |||
</td> | |||
<td class="name"> | |||
<span class="wrap"> | |||
{{if .IsDir}} | |||
<a href="{{$.BranchLink}}/{{.Path}}">{{.Name}}</a> | |||
{{else}} | |||
<a href="{{$.BranchLink}}/{{.Path}}">{{.Name}}</a> | |||
{{end}} | |||
</span> | |||
</td> | |||
<td class="text"> | |||
<span class="wrap"><a href="/{{$.Username}}/{{$.Reponame}}/commit/{{.Commit.Oid}}">{{.Commit.Message}}</a></span> | |||
</td> | |||
<td class="date"> | |||
<span class="wrap">{{TimeSince .Commit.Committer.When}}</span> | |||
</td> | |||
</tr> | |||
{{end}} | |||
{{if .HasParentPath}} | |||
<tr class="has-parent"> | |||
<td class="icon"><a href="{{.BranchLink}}{{.ParentPath}}"><i class="fa fa-reply"></i></a></td> | |||
<td class="name"><a href="{{.BranchLink}}{{.ParentPath}}">..</a></td> | |||
<td class="text"></td> | |||
<td class="date"></td> | |||
</tr> | |||
{{end}} | |||
{{range $item := .Files}} | |||
{{$entry := index $item 0}} | |||
{{$commit := index $item 1}} | |||
<tr {{if $entry.IsDir}}class="is-dir"{{end}}> | |||
<td class="icon"> | |||
<i class="fa {{if $entry.IsDir}}fa-folder{{else}}fa-file-text-o{{end}}"></i> | |||
</td> | |||
<td class="name"> | |||
<span class="wrap"> | |||
<a href="{{$.BranchLink}}/{{$.TreePath}}{{$entry.Name}}">{{$entry.Name}}</a> | |||
</span> | |||
</td> | |||
<td class="text"> | |||
<span class="wrap"><a href="/{{$.Username}}/{{$.Reponame}}/commit/{{$commit.Id}}">{{$commit.Message}}</a></span> | |||
</td> | |||
<td class="date"> | |||
<span class="wrap">{{TimeSince $commit.Committer.When}}</span> | |||
</td> | |||
</tr> | |||
{{end}} | |||
</tbody> | |||
</table> | |||
</div> | |||
{{if .ReadmeExist}} | |||
{{template "repo/single_file" .}} | |||
{{end}} | |||
{{end}} |