update with new git
This commit is contained in:
parent
9ffa8a4083
commit
52b4ab2aa5
10 changed files with 307 additions and 663 deletions
503
models/git.go
503
models/git.go
|
@ -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()
|
|
||||||
}
|
|
207
models/git_diff.go
Normal file
207
models/git_diff.go
Normal file
|
@ -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)
|
qlog.Fatalf("runUpdate.Open repoId: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
newOid, err := git.NewOidFromString(newCommitId)
|
newCommit, err := repo.GetCommit(newCommitId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
qlog.Fatalf("runUpdate.Ref repoId:%v err: %v", newCommitId, err)
|
qlog.Fatalf("runUpdate GetCommit of newCommitId: %v", err)
|
||||||
}
|
return
|
||||||
|
|
||||||
newCommit, err := repo.LookupCommit(newOid)
|
|
||||||
if err != nil {
|
|
||||||
qlog.Fatalf("runUpdate.Ref repoId: %v", err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var l *list.List
|
var l *list.List
|
||||||
// if a new branch
|
// if a new branch
|
||||||
if isNew {
|
if isNew {
|
||||||
l, err = repo.CommitsBefore(newCommit.Id())
|
l, err = newCommit.CommitsBefore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
qlog.Fatalf("Find CommitsBefore erro:", err)
|
qlog.Fatalf("Find CommitsBefore erro:", err)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
oldOid, err := git.NewOidFromString(oldCommitId)
|
l, err = newCommit.CommitsBeforeUntil(oldCommitId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
qlog.Fatalf("runUpdate.Ref repoId: %v", err)
|
qlog.Fatalf("Find CommitsBeforeUntil erro:", err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
oldCommit, err := repo.LookupCommit(oldOid)
|
|
||||||
if err != nil {
|
|
||||||
qlog.Fatalf("runUpdate.Ref repoId: %v", err)
|
|
||||||
}
|
|
||||||
l = repo.CommitsBetween(newCommit, oldCommit)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -76,7 +67,7 @@ func Update(refName, oldCommitId, newCommitId, userName, repoName string, userId
|
||||||
actEmail = commit.Committer.Email
|
actEmail = commit.Committer.Email
|
||||||
}
|
}
|
||||||
commits = append(commits,
|
commits = append(commits,
|
||||||
&base.PushCommit{commit.Id().String(),
|
&base.PushCommit{commit.Id.String(),
|
||||||
commit.Message(),
|
commit.Message(),
|
||||||
commit.Author.Email,
|
commit.Author.Email,
|
||||||
commit.Author.Name})
|
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()})
|
//commits = append(commits, []string{lastCommit.Id().String(), lastCommit.Message()})
|
||||||
if err = CommitRepoAction(userId, userName, actEmail,
|
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)
|
qlog.Fatalf("runUpdate.models.CommitRepoAction: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -131,7 +131,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
detect:
|
detect:
|
||||||
if len(branchName) > 0 {
|
if len(branchName) > 0 {
|
||||||
// TODO check tag
|
// TODO check tag
|
||||||
if models.IsBranchExist(user.Name, repoName, branchName) {
|
if gitRepo.IsBranchExist(branchName) {
|
||||||
ctx.Repo.IsBranch = true
|
ctx.Repo.IsBranch = true
|
||||||
ctx.Repo.BranchName = branchName
|
ctx.Repo.BranchName = branchName
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Repo.CommitId = ctx.Repo.Commit.Oid.String()
|
ctx.Repo.CommitId = ctx.Repo.Commit.Id.String()
|
||||||
|
|
||||||
} else if len(branchName) == 40 {
|
} else if len(branchName) == 40 {
|
||||||
ctx.Repo.IsCommit = true
|
ctx.Repo.IsCommit = true
|
||||||
|
@ -181,7 +181,7 @@ func RepoAssignment(redirect bool, args ...bool) martini.Handler {
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
ctx.Data["BranchName"] = ctx.Repo.BranchName
|
||||||
brs, err := models.GetBranches(user.Name, repoName)
|
brs, err := ctx.Repo.GitRepo.GetBranches()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("RepoAssignment(GetBranches): %v", err)
|
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 (
|
import (
|
||||||
"github.com/go-martini/martini"
|
"github.com/go-martini/martini"
|
||||||
|
|
||||||
"github.com/gogits/gogs/models"
|
|
||||||
"github.com/gogits/gogs/modules/middleware"
|
"github.com/gogits/gogs/modules/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Branches(ctx *middleware.Context, params martini.Params) {
|
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 {
|
if err != nil {
|
||||||
ctx.Handle(404, "repo.Branches", err)
|
ctx.Handle(404, "repo.Branches", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"container/list"
|
|
||||||
"path"
|
"path"
|
||||||
|
|
||||||
"github.com/go-martini/martini"
|
"github.com/go-martini/martini"
|
||||||
|
@ -16,11 +15,10 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func Commits(ctx *middleware.Context, params martini.Params) {
|
func Commits(ctx *middleware.Context, params martini.Params) {
|
||||||
userName := params["username"]
|
userName := ctx.Repo.Owner.Name
|
||||||
repoName := params["reponame"]
|
repoName := ctx.Repo.Repository.Name
|
||||||
branchName := params["branchname"]
|
|
||||||
|
|
||||||
brs, err := models.GetBranches(userName, repoName)
|
brs, err := ctx.Repo.GitRepo.GetBranches()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(500, "repo.Commits", err)
|
ctx.Handle(500, "repo.Commits", err)
|
||||||
return
|
return
|
||||||
|
@ -29,8 +27,7 @@ func Commits(ctx *middleware.Context, params martini.Params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
repoPath := models.RepoPath(userName, repoName)
|
commitsCount, err := ctx.Repo.Commit.CommitsCount()
|
||||||
commitsCount, err := models.GetCommitsCount(repoPath, branchName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(500, "repo.Commits(GetCommitsCount)", err)
|
ctx.Handle(500, "repo.Commits(GetCommitsCount)", err)
|
||||||
return
|
return
|
||||||
|
@ -51,7 +48,7 @@ func Commits(ctx *middleware.Context, params martini.Params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//both `git log branchName` and `git log commitId` work
|
//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 {
|
if err != nil {
|
||||||
ctx.Handle(500, "repo.Commits(get commits)", err)
|
ctx.Handle(500, "repo.Commits(get commits)", err)
|
||||||
return
|
return
|
||||||
|
@ -70,7 +67,6 @@ func Commits(ctx *middleware.Context, params martini.Params) {
|
||||||
func Diff(ctx *middleware.Context, params martini.Params) {
|
func Diff(ctx *middleware.Context, params martini.Params) {
|
||||||
userName := ctx.Repo.Owner.Name
|
userName := ctx.Repo.Owner.Name
|
||||||
repoName := ctx.Repo.Repository.Name
|
repoName := ctx.Repo.Repository.Name
|
||||||
branchName := ctx.Repo.BranchName
|
|
||||||
commitId := ctx.Repo.CommitId
|
commitId := ctx.Repo.CommitId
|
||||||
|
|
||||||
commit := ctx.Repo.Commit
|
commit := ctx.Repo.Commit
|
||||||
|
@ -82,19 +78,15 @@ func Diff(ctx *middleware.Context, params martini.Params) {
|
||||||
}
|
}
|
||||||
|
|
||||||
isImageFile := func(name string) bool {
|
isImageFile := func(name string) bool {
|
||||||
repoFile, err := models.GetTargetFile(userName, repoName,
|
blob, err := ctx.Repo.Commit.GetBlobByPath(name)
|
||||||
branchName, commitId, name)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
blob, err := repoFile.LookupBlob()
|
data, err := blob.Data()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
data := blob.Contents()
|
|
||||||
_, isImage := base.IsImageFile(data)
|
_, isImage := base.IsImageFile(data)
|
||||||
return isImage
|
return isImage
|
||||||
}
|
}
|
||||||
|
@ -119,9 +111,8 @@ func SearchCommits(ctx *middleware.Context, params martini.Params) {
|
||||||
|
|
||||||
userName := params["username"]
|
userName := params["username"]
|
||||||
repoName := params["reponame"]
|
repoName := params["reponame"]
|
||||||
branchName := params["branchname"]
|
|
||||||
|
|
||||||
brs, err := models.GetBranches(userName, repoName)
|
brs, err := ctx.Repo.GitRepo.GetBranches()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(500, "repo.SearchCommits(GetBranches)", err)
|
ctx.Handle(500, "repo.SearchCommits(GetBranches)", err)
|
||||||
return
|
return
|
||||||
|
@ -130,11 +121,8 @@ func SearchCommits(ctx *middleware.Context, params martini.Params) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var commits *list.List
|
commits, err := ctx.Repo.Commit.SearchCommits(keyword)
|
||||||
if !models.IsBranchExist(userName, repoName, branchName) {
|
if err != nil {
|
||||||
ctx.Handle(404, "repo.SearchCommits(IsBranchExist)", err)
|
|
||||||
return
|
|
||||||
} else if commits, err = models.SearchCommits(models.RepoPath(userName, repoName), branchName, keyword); err != nil {
|
|
||||||
ctx.Handle(500, "repo.SearchCommits(SearchCommits)", err)
|
ctx.Handle(500, "repo.SearchCommits(SearchCommits)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
package repo
|
package repo
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/gogits/gogs/models"
|
|
||||||
"github.com/gogits/gogs/modules/middleware"
|
"github.com/gogits/gogs/modules/middleware"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -13,7 +12,7 @@ func Releases(ctx *middleware.Context) {
|
||||||
ctx.Data["Title"] = "Releases"
|
ctx.Data["Title"] = "Releases"
|
||||||
ctx.Data["IsRepoToolbarReleases"] = true
|
ctx.Data["IsRepoToolbarReleases"] = true
|
||||||
ctx.Data["IsRepoReleaseNew"] = false
|
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 {
|
if err != nil {
|
||||||
ctx.Handle(404, "repo.Releases(GetTags)", err)
|
ctx.Handle(404, "repo.Releases(GetTags)", err)
|
||||||
return
|
return
|
||||||
|
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"github.com/gogits/git"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -107,7 +108,6 @@ func MigratePost(ctx *middleware.Context, form auth.MigrateRepoForm) {
|
||||||
|
|
||||||
func Single(ctx *middleware.Context, params martini.Params) {
|
func Single(ctx *middleware.Context, params martini.Params) {
|
||||||
branchName := ctx.Repo.BranchName
|
branchName := ctx.Repo.BranchName
|
||||||
commitId := ctx.Repo.CommitId
|
|
||||||
userName := ctx.Repo.Owner.Name
|
userName := ctx.Repo.Owner.Name
|
||||||
repoName := ctx.Repo.Repository.Name
|
repoName := ctx.Repo.Repository.Name
|
||||||
|
|
||||||
|
@ -125,46 +125,42 @@ func Single(ctx *middleware.Context, params martini.Params) {
|
||||||
|
|
||||||
ctx.Data["IsRepoToolbarSource"] = true
|
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
|
isViewBranch := ctx.Repo.IsBranch
|
||||||
ctx.Data["IsViewBranch"] = isViewBranch
|
ctx.Data["IsViewBranch"] = isViewBranch
|
||||||
|
|
||||||
repoFile, err := models.GetTargetFile(userName, repoName,
|
treePath := treename
|
||||||
branchName, commitId, treename)
|
if len(treePath) != 0 {
|
||||||
|
treePath = treePath + "/"
|
||||||
|
}
|
||||||
|
|
||||||
if err != nil && err != models.ErrRepoFileNotExist {
|
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(treename)
|
||||||
ctx.Handle(404, "repo.Single(GetTargetFile)", err)
|
|
||||||
|
if err != nil && err != git.ErrNotExist {
|
||||||
|
ctx.Handle(404, "repo.Single(GetTreeEntryByPath)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(treename) != 0 && repoFile == nil {
|
if len(treename) != 0 && entry == nil {
|
||||||
ctx.Handle(404, "repo.Single", nil)
|
ctx.Handle(404, "repo.Single", nil)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if repoFile != nil && repoFile.IsFile() {
|
if entry != nil && entry.IsFile() {
|
||||||
if blob, err := repoFile.LookupBlob(); err != nil {
|
blob := entry.Blob()
|
||||||
ctx.Handle(404, "repo.Single(repoFile.LookupBlob)", err)
|
|
||||||
|
if data, err := blob.Data(); err != nil {
|
||||||
|
ctx.Handle(404, "repo.Single(blob.Data)", err)
|
||||||
} else {
|
} else {
|
||||||
ctx.Data["FileSize"] = repoFile.Size
|
ctx.Data["FileSize"] = blob.Size()
|
||||||
ctx.Data["IsFile"] = true
|
ctx.Data["IsFile"] = true
|
||||||
ctx.Data["FileName"] = repoFile.Name
|
ctx.Data["FileName"] = blob.Name
|
||||||
ext := path.Ext(repoFile.Name)
|
ext := path.Ext(blob.Name)
|
||||||
if len(ext) > 0 {
|
if len(ext) > 0 {
|
||||||
ext = ext[1:]
|
ext = ext[1:]
|
||||||
}
|
}
|
||||||
ctx.Data["FileExt"] = ext
|
ctx.Data["FileExt"] = ext
|
||||||
ctx.Data["FileLink"] = rawLink + "/" + treename
|
ctx.Data["FileLink"] = rawLink + "/" + treename
|
||||||
|
|
||||||
data := blob.Contents()
|
|
||||||
_, isTextFile := base.IsTextFile(data)
|
_, isTextFile := base.IsTextFile(data)
|
||||||
_, isImageFile := base.IsImageFile(data)
|
_, isImageFile := base.IsImageFile(data)
|
||||||
ctx.Data["FileIsText"] = isTextFile
|
ctx.Data["FileIsText"] = isTextFile
|
||||||
|
@ -172,7 +168,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
|
||||||
if isImageFile {
|
if isImageFile {
|
||||||
ctx.Data["IsImageFile"] = true
|
ctx.Data["IsImageFile"] = true
|
||||||
} else {
|
} else {
|
||||||
readmeExist := base.IsMarkdownFile(repoFile.Name) || base.IsReadmeFile(repoFile.Name)
|
readmeExist := base.IsMarkdownFile(blob.Name) || base.IsReadmeFile(blob.Name)
|
||||||
ctx.Data["ReadmeExist"] = readmeExist
|
ctx.Data["ReadmeExist"] = readmeExist
|
||||||
if readmeExist {
|
if readmeExist {
|
||||||
ctx.Data["FileContent"] = string(base.RenderMarkdown(data, ""))
|
ctx.Data["FileContent"] = string(base.RenderMarkdown(data, ""))
|
||||||
|
@ -186,21 +182,35 @@ func Single(ctx *middleware.Context, params martini.Params) {
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// Directory and file list.
|
// Directory and file list.
|
||||||
files, err := models.GetReposFiles(userName, repoName, ctx.Repo.CommitId, treename)
|
tree, err := ctx.Repo.Commit.SubTree(treename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(404, "repo.Single(GetReposFiles)", err)
|
ctx.Handle(404, "repo.Single(SubTree)", err)
|
||||||
return
|
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
|
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) {
|
if !f.IsFile() || !base.IsReadmeFile(f.Name) {
|
||||||
continue
|
continue
|
||||||
} else {
|
} else {
|
||||||
readmeFile = f
|
readmeFile = f.Blob()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -208,13 +218,12 @@ func Single(ctx *middleware.Context, params martini.Params) {
|
||||||
if readmeFile != nil {
|
if readmeFile != nil {
|
||||||
ctx.Data["ReadmeInSingle"] = true
|
ctx.Data["ReadmeInSingle"] = true
|
||||||
ctx.Data["ReadmeExist"] = 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)
|
ctx.Handle(404, "repo.Single(readmeFile.LookupBlob)", err)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
ctx.Data["FileSize"] = readmeFile.Size
|
ctx.Data["FileSize"] = readmeFile.Size
|
||||||
ctx.Data["FileLink"] = rawLink + "/" + treename
|
ctx.Data["FileLink"] = rawLink + "/" + treename
|
||||||
data := blob.Contents()
|
|
||||||
_, isTextFile := base.IsTextFile(data)
|
_, isTextFile := base.IsTextFile(data)
|
||||||
ctx.Data["FileIsText"] = isTextFile
|
ctx.Data["FileIsText"] = isTextFile
|
||||||
ctx.Data["FileName"] = readmeFile.Name
|
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["LastCommit"] = ctx.Repo.Commit
|
||||||
ctx.Data["Paths"] = Paths
|
ctx.Data["Paths"] = Paths
|
||||||
ctx.Data["Treenames"] = treenames
|
ctx.Data["Treenames"] = treenames
|
||||||
|
ctx.Data["TreePath"] = treePath
|
||||||
ctx.Data["BranchLink"] = branchLink
|
ctx.Data["BranchLink"] = branchLink
|
||||||
ctx.HTML(200, "repo/single")
|
ctx.HTML(200, "repo/single")
|
||||||
}
|
}
|
||||||
|
@ -254,31 +264,18 @@ func SingleDownload(ctx *middleware.Context, params martini.Params) {
|
||||||
// Get tree path
|
// Get tree path
|
||||||
treename := params["_1"]
|
treename := params["_1"]
|
||||||
|
|
||||||
branchName := params["branchname"]
|
blob, err := ctx.Repo.Commit.GetBlobByPath(treename)
|
||||||
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)
|
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(404, "repo.SingleDownload(GetTargetFile)", err)
|
ctx.Handle(404, "repo.SingleDownload(GetBlobByPath)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
blob, err := repoFile.LookupBlob()
|
data, err := blob.Data()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ctx.Handle(404, "repo.SingleDownload(LookupBlob)", err)
|
ctx.Handle(404, "repo.SingleDownload(Data)", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := blob.Contents()
|
|
||||||
contentType, isTextFile := base.IsTextFile(data)
|
contentType, isTextFile := base.IsTextFile(data)
|
||||||
_, isImageFile := base.IsImageFile(data)
|
_, isImageFile := base.IsImageFile(data)
|
||||||
ctx.Res.Header().Set("Content-Type", contentType)
|
ctx.Res.Header().Set("Content-Type", contentType)
|
||||||
|
@ -361,7 +358,8 @@ func SettingPost(ctx *middleware.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
br := ctx.Query("branch")
|
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.DefaultBranch = br
|
||||||
}
|
}
|
||||||
ctx.Repo.Repository.Description = ctx.Query("desc")
|
ctx.Repo.Repository.Description = ctx.Query("desc")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<div class="panel panel-default info-box">
|
<div class="panel panel-default info-box">
|
||||||
<div class="panel-heading info-head">
|
<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>
|
||||||
<div class="panel-body info-content">
|
<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>
|
<a href="/user/{{.LastCommit.Author.Name}}">{{.LastCommit.Author.Name}}</a> <span class="text-muted">{{TimeSince .LastCommit.Author.When}}</span>
|
||||||
|
@ -15,40 +15,37 @@
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
{{if .HasParentPath}}
|
{{if .HasParentPath}}
|
||||||
<tr class="has-parent">
|
<tr class="has-parent">
|
||||||
<td class="icon"><a href="{{.BranchLink}}{{.ParentPath}}"><i class="fa fa-reply"></i></a></td>
|
<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="name"><a href="{{.BranchLink}}{{.ParentPath}}">..</a></td>
|
||||||
<td class="text"></td>
|
<td class="text"></td>
|
||||||
<td class="date"></td>
|
<td class="date"></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
{{range .Files}}
|
{{range $item := .Files}}
|
||||||
<tr
|
{{$entry := index $item 0}}
|
||||||
{{if .IsDir}}class="is-dir"{{end}}>
|
{{$commit := index $item 1}}
|
||||||
<td class="icon">
|
<tr {{if $entry.IsDir}}class="is-dir"{{end}}>
|
||||||
<i class="fa {{if .IsDir}}fa-folder{{else}}fa-file-text-o{{end}}"></i>
|
<td class="icon">
|
||||||
</td>
|
<i class="fa {{if $entry.IsDir}}fa-folder{{else}}fa-file-text-o{{end}}"></i>
|
||||||
<td class="name">
|
</td>
|
||||||
<span class="wrap">
|
<td class="name">
|
||||||
{{if .IsDir}}
|
<span class="wrap">
|
||||||
<a href="{{$.BranchLink}}/{{.Path}}">{{.Name}}</a>
|
<a href="{{$.BranchLink}}/{{$.TreePath}}{{$entry.Name}}">{{$entry.Name}}</a>
|
||||||
{{else}}
|
</span>
|
||||||
<a href="{{$.BranchLink}}/{{.Path}}">{{.Name}}</a>
|
</td>
|
||||||
{{end}}
|
<td class="text">
|
||||||
</span>
|
<span class="wrap"><a href="/{{$.Username}}/{{$.Reponame}}/commit/{{$commit.Id}}">{{$commit.Message}}</a></span>
|
||||||
</td>
|
</td>
|
||||||
<td class="text">
|
<td class="date">
|
||||||
<span class="wrap"><a href="/{{$.Username}}/{{$.Reponame}}/commit/{{.Commit.Oid}}">{{.Commit.Message}}</a></span>
|
<span class="wrap">{{TimeSince $commit.Committer.When}}</span>
|
||||||
</td>
|
</td>
|
||||||
<td class="date">
|
</tr>
|
||||||
<span class="wrap">{{TimeSince .Commit.Committer.When}}</span>
|
{{end}}
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{{end}}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{{if .ReadmeExist}}
|
{{if .ReadmeExist}}
|
||||||
{{template "repo/single_file" .}}
|
{{template "repo/single_file" .}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Reference in a new issue