summaryrefslogtreecommitdiffstats
path: root/vendor/code.gitea.io
diff options
context:
space:
mode:
authorSandro Santilli <strk@kbt.io>2016-11-10 17:24:48 +0100
committerThibault Meyer <0xbaadf00d@users.noreply.github.com>2016-11-10 17:24:48 +0100
commit4247304f5aeb791e3e201947478eef4964744146 (patch)
tree47a27cdaafe235512921fb1aba4a5c6738e4c384 /vendor/code.gitea.io
parent1c0a4e166fc3c37ebed528fc41b1cbca5a00556d (diff)
downloadgitea-4247304f5aeb791e3e201947478eef4964744146.tar.gz
gitea-4247304f5aeb791e3e201947478eef4964744146.zip
Update import paths from github.com/go-gitea to code.gitea.io (#135)
- Update import paths from github.com/go-gitea to code.gitea.io - Fix import path for travis See https://docs.travis-ci.com/user/languages/go#Go-Import-Path
Diffstat (limited to 'vendor/code.gitea.io')
-rw-r--r--vendor/code.gitea.io/git/LICENSE19
-rw-r--r--vendor/code.gitea.io/git/README.md13
-rw-r--r--vendor/code.gitea.io/git/blob.go30
-rw-r--r--vendor/code.gitea.io/git/command.go139
-rw-r--r--vendor/code.gitea.io/git/commit.go250
-rw-r--r--vendor/code.gitea.io/git/commit_archive.go33
-rw-r--r--vendor/code.gitea.io/git/error.go50
-rw-r--r--vendor/code.gitea.io/git/git.go80
-rw-r--r--vendor/code.gitea.io/git/hook.go121
-rw-r--r--vendor/code.gitea.io/git/repo.go193
-rw-r--r--vendor/code.gitea.io/git/repo_branch.go119
-rw-r--r--vendor/code.gitea.io/git/repo_commit.go353
-rw-r--r--vendor/code.gitea.io/git/repo_hook.go13
-rw-r--r--vendor/code.gitea.io/git/repo_object.go14
-rw-r--r--vendor/code.gitea.io/git/repo_pull.go75
-rw-r--r--vendor/code.gitea.io/git/repo_tag.go120
-rw-r--r--vendor/code.gitea.io/git/repo_tree.go26
-rw-r--r--vendor/code.gitea.io/git/sha1.go93
-rw-r--r--vendor/code.gitea.io/git/signature.go48
-rw-r--r--vendor/code.gitea.io/git/submodule.go78
-rw-r--r--vendor/code.gitea.io/git/tag.go65
-rw-r--r--vendor/code.gitea.io/git/tree.go151
-rw-r--r--vendor/code.gitea.io/git/tree_blob.go57
-rw-r--r--vendor/code.gitea.io/git/tree_entry.go209
-rw-r--r--vendor/code.gitea.io/git/utlis.go93
-rw-r--r--vendor/code.gitea.io/go-sdk/LICENSE20
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/admin_org.go21
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/admin_repo.go21
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/admin_user.go68
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/gitea.go90
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/issue.go92
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/issue_comment.go57
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/issue_label.go98
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/issue_milestone.go69
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/miscellaneous.go11
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/org.go60
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/org_member.go24
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/org_team.go18
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/pull.go37
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/repo.go125
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/repo_branch.go25
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/repo_collaborator.go24
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/repo_file.go15
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/repo_hook.go245
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/repo_key.go50
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/user.go24
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/user_app.go46
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/user_email.go43
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/user_follow.go47
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/user_key.go49
-rw-r--r--vendor/code.gitea.io/go-sdk/gitea/utils.go23
51 files changed, 3844 insertions, 0 deletions
diff --git a/vendor/code.gitea.io/git/LICENSE b/vendor/code.gitea.io/git/LICENSE
new file mode 100644
index 0000000000..176d8dfe01
--- /dev/null
+++ b/vendor/code.gitea.io/git/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2015 All Gogs Contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE. \ No newline at end of file
diff --git a/vendor/code.gitea.io/git/README.md b/vendor/code.gitea.io/git/README.md
new file mode 100644
index 0000000000..b9e34bcf02
--- /dev/null
+++ b/vendor/code.gitea.io/git/README.md
@@ -0,0 +1,13 @@
+# Git Shell [![Build # Status](https://travis-ci.org/go-gitea/git.svg?branch=master)](https://travis-ci.org/go-gitea/git)
+
+Package git is a Go module for Git access through shell commands.
+
+## Limitations
+
+- Go version must be at least **1.3**.
+- Git version must be no less than **1.7.1**, and great than or equal to **1.8.0** is recommended.
+- For Windows users, try use as higher version as possible.
+
+## License
+
+This project is under the MIT License. See the [LICENSE](LICENSE) file for the full license text.
diff --git a/vendor/code.gitea.io/git/blob.go b/vendor/code.gitea.io/git/blob.go
new file mode 100644
index 0000000000..478682e715
--- /dev/null
+++ b/vendor/code.gitea.io/git/blob.go
@@ -0,0 +1,30 @@
+// Copyright 2015 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 git
+
+import (
+ "bytes"
+ "io"
+)
+
+// Blob represents a Git object.
+type Blob struct {
+ repo *Repository
+ *TreeEntry
+}
+
+// Data gets content of blob all at once and wrap it as io.Reader.
+// This can be very slow and memory consuming for huge content.
+func (b *Blob) Data() (io.Reader, error) {
+ stdout, err := NewCommand("show", b.ID.String()).RunInDirBytes(b.repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ return bytes.NewBuffer(stdout), nil
+}
+
+func (b *Blob) DataPipeline(stdout, stderr io.Writer) error {
+ return NewCommand("show", b.ID.String()).RunInDirPipeline(b.repo.Path, stdout, stderr)
+}
diff --git a/vendor/code.gitea.io/git/command.go b/vendor/code.gitea.io/git/command.go
new file mode 100644
index 0000000000..f7fce67bee
--- /dev/null
+++ b/vendor/code.gitea.io/git/command.go
@@ -0,0 +1,139 @@
+// Copyright 2015 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 git
+
+import (
+ "bytes"
+ "fmt"
+ "io"
+ "os/exec"
+ "strings"
+ "time"
+)
+
+// Command represents a command with its subcommands or arguments.
+type Command struct {
+ name string
+ args []string
+}
+
+func (c *Command) String() string {
+ if len(c.args) == 0 {
+ return c.name
+ }
+ return fmt.Sprintf("%s %s", c.name, strings.Join(c.args, " "))
+}
+
+// NewCommand creates and returns a new Git Command based on given command and arguments.
+func NewCommand(args ...string) *Command {
+ return &Command{
+ name: "git",
+ args: args,
+ }
+}
+
+// AddArguments adds new argument(s) to the command.
+func (c *Command) AddArguments(args ...string) *Command {
+ c.args = append(c.args, args...)
+ return c
+}
+
+const DEFAULT_TIMEOUT = 60 * time.Second
+
+// RunInDirTimeoutPipeline executes the command in given directory with given timeout,
+// it pipes stdout and stderr to given io.Writer.
+func (c *Command) RunInDirTimeoutPipeline(timeout time.Duration, dir string, stdout, stderr io.Writer) error {
+ if timeout == -1 {
+ timeout = DEFAULT_TIMEOUT
+ }
+
+ if len(dir) == 0 {
+ log(c.String())
+ } else {
+ log("%s: %v", dir, c)
+ }
+
+ cmd := exec.Command(c.name, c.args...)
+ cmd.Dir = dir
+ cmd.Stdout = stdout
+ cmd.Stderr = stderr
+ if err := cmd.Start(); err != nil {
+ return err
+ }
+
+ done := make(chan error)
+ go func() {
+ done <- cmd.Wait()
+ }()
+
+ var err error
+ select {
+ case <-time.After(timeout):
+ if cmd.Process != nil && cmd.ProcessState != nil && !cmd.ProcessState.Exited() {
+ if err := cmd.Process.Kill(); err != nil {
+ return fmt.Errorf("fail to kill process: %v", err)
+ }
+ }
+
+ <-done
+ return ErrExecTimeout{timeout}
+ case err = <-done:
+ }
+
+ return err
+}
+
+// RunInDirTimeout executes the command in given directory with given timeout,
+// and returns stdout in []byte and error (combined with stderr).
+func (c *Command) RunInDirTimeout(timeout time.Duration, dir string) ([]byte, error) {
+ stdout := new(bytes.Buffer)
+ stderr := new(bytes.Buffer)
+ if err := c.RunInDirTimeoutPipeline(timeout, dir, stdout, stderr); err != nil {
+ return nil, concatenateError(err, stderr.String())
+ }
+
+ if stdout.Len() > 0 {
+ log("stdout:\n%s", stdout.Bytes()[:1024])
+ }
+ return stdout.Bytes(), nil
+}
+
+// RunInDirPipeline executes the command in given directory,
+// it pipes stdout and stderr to given io.Writer.
+func (c *Command) RunInDirPipeline(dir string, stdout, stderr io.Writer) error {
+ return c.RunInDirTimeoutPipeline(-1, dir, stdout, stderr)
+}
+
+// RunInDir executes the command in given directory
+// and returns stdout in []byte and error (combined with stderr).
+func (c *Command) RunInDirBytes(dir string) ([]byte, error) {
+ return c.RunInDirTimeout(-1, dir)
+}
+
+// RunInDir executes the command in given directory
+// and returns stdout in string and error (combined with stderr).
+func (c *Command) RunInDir(dir string) (string, error) {
+ stdout, err := c.RunInDirTimeout(-1, dir)
+ if err != nil {
+ return "", err
+ }
+ return string(stdout), nil
+}
+
+// RunTimeout executes the command in defualt working directory with given timeout,
+// and returns stdout in string and error (combined with stderr).
+func (c *Command) RunTimeout(timeout time.Duration) (string, error) {
+ stdout, err := c.RunInDirTimeout(timeout, "")
+ if err != nil {
+ return "", err
+ }
+ return string(stdout), nil
+}
+
+// Run executes the command in defualt working directory
+// and returns stdout in string and error (combined with stderr).
+func (c *Command) Run() (string, error) {
+ return c.RunTimeout(-1)
+}
diff --git a/vendor/code.gitea.io/git/commit.go b/vendor/code.gitea.io/git/commit.go
new file mode 100644
index 0000000000..e16246f982
--- /dev/null
+++ b/vendor/code.gitea.io/git/commit.go
@@ -0,0 +1,250 @@
+// Copyright 2015 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 git
+
+import (
+ "bufio"
+ "container/list"
+ "fmt"
+ "net/http"
+ "strconv"
+ "strings"
+
+ "github.com/mcuadros/go-version"
+)
+
+// Commit represents a git commit.
+type Commit struct {
+ Tree
+ ID sha1 // The ID of this commit object
+ Author *Signature
+ Committer *Signature
+ CommitMessage string
+
+ parents []sha1 // SHA1 strings
+ submoduleCache *objectCache
+}
+
+// Message returns the commit message. Same as retrieving CommitMessage directly.
+func (c *Commit) Message() string {
+ return c.CommitMessage
+}
+
+// Summary returns first line of commit message.
+func (c *Commit) Summary() string {
+ return strings.Split(c.CommitMessage, "\n")[0]
+}
+
+// ParentID returns oid of n-th parent (0-based index).
+// It returns nil if no such parent exists.
+func (c *Commit) ParentID(n int) (sha1, error) {
+ if n >= len(c.parents) {
+ return sha1{}, ErrNotExist{"", ""}
+ }
+ return c.parents[n], nil
+}
+
+// Parent returns n-th parent (0-based index) of the commit.
+func (c *Commit) Parent(n int) (*Commit, error) {
+ id, err := c.ParentID(n)
+ if err != nil {
+ return nil, err
+ }
+ parent, err := c.repo.getCommit(id)
+ if err != nil {
+ return nil, err
+ }
+ return parent, nil
+}
+
+// ParentCount returns number of parents of the commit.
+// 0 if this is the root commit, otherwise 1,2, etc.
+func (c *Commit) ParentCount() int {
+ return len(c.parents)
+}
+
+func isImageFile(data []byte) (string, bool) {
+ contentType := http.DetectContentType(data)
+ if strings.Index(contentType, "image/") != -1 {
+ return contentType, true
+ }
+ return contentType, false
+}
+
+func (c *Commit) IsImageFile(name string) bool {
+ blob, err := c.GetBlobByPath(name)
+ if err != nil {
+ return false
+ }
+
+ dataRc, err := blob.Data()
+ if err != nil {
+ return false
+ }
+ buf := make([]byte, 1024)
+ n, _ := dataRc.Read(buf)
+ buf = buf[:n]
+ _, isImage := isImageFile(buf)
+ return isImage
+}
+
+// GetCommitByPath return the commit of relative path object.
+func (c *Commit) GetCommitByPath(relpath string) (*Commit, error) {
+ return c.repo.getCommitByPathWithID(c.ID, relpath)
+}
+
+// AddAllChanges marks local changes to be ready for commit.
+func AddChanges(repoPath string, all bool, files ...string) error {
+ cmd := NewCommand("add")
+ if all {
+ cmd.AddArguments("--all")
+ }
+ _, err := cmd.AddArguments(files...).RunInDir(repoPath)
+ return err
+}
+
+type CommitChangesOptions struct {
+ Committer *Signature
+ Author *Signature
+ Message string
+}
+
+// CommitChanges commits local changes with given committer, author and message.
+// If author is nil, it will be the same as committer.
+func CommitChanges(repoPath string, opts CommitChangesOptions) error {
+ cmd := NewCommand()
+ if opts.Committer != nil {
+ cmd.AddArguments("-c", "user.name="+opts.Committer.Name, "-c", "user.email="+opts.Committer.Email)
+ }
+ cmd.AddArguments("commit")
+
+ if opts.Author == nil {
+ opts.Author = opts.Committer
+ }
+ if opts.Author != nil {
+ cmd.AddArguments(fmt.Sprintf("--author='%s <%s>'", opts.Author.Name, opts.Author.Email))
+ }
+ cmd.AddArguments("-m", opts.Message)
+
+ _, err := cmd.RunInDir(repoPath)
+ // No stderr but exit status 1 means nothing to commit.
+ if err != nil && err.Error() == "exit status 1" {
+ return nil
+ }
+ return err
+}
+
+func commitsCount(repoPath, revision, relpath string) (int64, error) {
+ var cmd *Command
+ isFallback := false
+ if version.Compare(gitVersion, "1.8.0", "<") {
+ isFallback = true
+ cmd = NewCommand("log", "--pretty=format:''")
+ } else {
+ cmd = NewCommand("rev-list", "--count")
+ }
+ cmd.AddArguments(revision)
+ if len(relpath) > 0 {
+ cmd.AddArguments("--", relpath)
+ }
+
+ stdout, err := cmd.RunInDir(repoPath)
+ if err != nil {
+ return 0, err
+ }
+
+ if isFallback {
+ return int64(strings.Count(stdout, "\n")) + 1, nil
+ }
+ return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
+}
+
+// CommitsCount returns number of total commits of until given revision.
+func CommitsCount(repoPath, revision string) (int64, error) {
+ return commitsCount(repoPath, revision, "")
+}
+
+func (c *Commit) CommitsCount() (int64, error) {
+ return CommitsCount(c.repo.Path, c.ID.String())
+}
+
+func (c *Commit) CommitsByRange(page int) (*list.List, error) {
+ return c.repo.commitsByRange(c.ID, page)
+}
+
+func (c *Commit) CommitsBefore() (*list.List, error) {
+ return c.repo.getCommitsBefore(c.ID)
+}
+
+func (c *Commit) CommitsBeforeLimit(num int) (*list.List, error) {
+ return c.repo.getCommitsBeforeLimit(c.ID, num)
+}
+
+func (c *Commit) CommitsBeforeUntil(commitID string) (*list.List, error) {
+ endCommit, err := c.repo.GetCommit(commitID)
+ if err != nil {
+ return nil, err
+ }
+ return c.repo.CommitsBetween(c, endCommit)
+}
+
+func (c *Commit) SearchCommits(keyword string) (*list.List, error) {
+ return c.repo.searchCommits(c.ID, keyword)
+}
+
+func (c *Commit) GetFilesChangedSinceCommit(pastCommit string) ([]string, error) {
+ return c.repo.getFilesChanged(pastCommit, c.ID.String())
+}
+
+func (c *Commit) GetSubModules() (*objectCache, error) {
+ if c.submoduleCache != nil {
+ return c.submoduleCache, nil
+ }
+
+ entry, err := c.GetTreeEntryByPath(".gitmodules")
+ if err != nil {
+ return nil, err
+ }
+ rd, err := entry.Blob().Data()
+ if err != nil {
+ return nil, err
+ }
+
+ scanner := bufio.NewScanner(rd)
+ c.submoduleCache = newObjectCache()
+ var ismodule bool
+ var path string
+ for scanner.Scan() {
+ if strings.HasPrefix(scanner.Text(), "[submodule") {
+ ismodule = true
+ continue
+ }
+ if ismodule {
+ fields := strings.Split(scanner.Text(), "=")
+ k := strings.TrimSpace(fields[0])
+ if k == "path" {
+ path = strings.TrimSpace(fields[1])
+ } else if k == "url" {
+ c.submoduleCache.Set(path, &SubModule{path, strings.TrimSpace(fields[1])})
+ ismodule = false
+ }
+ }
+ }
+
+ return c.submoduleCache, nil
+}
+
+func (c *Commit) GetSubModule(entryname string) (*SubModule, error) {
+ modules, err := c.GetSubModules()
+ if err != nil {
+ return nil, err
+ }
+
+ module, has := modules.Get(entryname)
+ if has {
+ return module.(*SubModule), nil
+ }
+ return nil, nil
+}
diff --git a/vendor/code.gitea.io/git/commit_archive.go b/vendor/code.gitea.io/git/commit_archive.go
new file mode 100644
index 0000000000..1066ba69c4
--- /dev/null
+++ b/vendor/code.gitea.io/git/commit_archive.go
@@ -0,0 +1,33 @@
+// Copyright 2015 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 git
+
+import (
+ "fmt"
+ "path/filepath"
+ "strings"
+)
+
+type ArchiveType int
+
+const (
+ ZIP ArchiveType = iota + 1
+ TARGZ
+)
+
+func (c *Commit) CreateArchive(target 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)
+ }
+
+ _, err := NewCommand("archive", "--prefix="+filepath.Base(strings.TrimSuffix(c.repo.Path, ".git"))+"/", "--format="+format, "-o", target, c.ID.String()).RunInDir(c.repo.Path)
+ return err
+}
diff --git a/vendor/code.gitea.io/git/error.go b/vendor/code.gitea.io/git/error.go
new file mode 100644
index 0000000000..848bfba127
--- /dev/null
+++ b/vendor/code.gitea.io/git/error.go
@@ -0,0 +1,50 @@
+// Copyright 2015 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 git
+
+import (
+ "fmt"
+ "time"
+)
+
+type ErrExecTimeout struct {
+ Duration time.Duration
+}
+
+func IsErrExecTimeout(err error) bool {
+ _, ok := err.(ErrExecTimeout)
+ return ok
+}
+
+func (err ErrExecTimeout) Error() string {
+ return fmt.Sprintf("execution is timeout [duration: %v]", err.Duration)
+}
+
+type ErrNotExist struct {
+ ID string
+ RelPath string
+}
+
+func IsErrNotExist(err error) bool {
+ _, ok := err.(ErrNotExist)
+ return ok
+}
+
+func (err ErrNotExist) Error() string {
+ return fmt.Sprintf("object does not exist [id: %s, rel_path: %s]", err.ID, err.RelPath)
+}
+
+type ErrUnsupportedVersion struct {
+ Required string
+}
+
+func IsErrUnsupportedVersion(err error) bool {
+ _, ok := err.(ErrUnsupportedVersion)
+ return ok
+}
+
+func (err ErrUnsupportedVersion) Error() string {
+ return fmt.Sprintf("Operation requires higher version [required: %s]", err.Required)
+}
diff --git a/vendor/code.gitea.io/git/git.go b/vendor/code.gitea.io/git/git.go
new file mode 100644
index 0000000000..71a9a37f42
--- /dev/null
+++ b/vendor/code.gitea.io/git/git.go
@@ -0,0 +1,80 @@
+// Copyright 2015 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 git
+
+import (
+ "fmt"
+ "strings"
+ "time"
+)
+
+const _VERSION = "0.4.2"
+
+func Version() string {
+ return _VERSION
+}
+
+var (
+ // Debug enables verbose logging on everything.
+ // This should be false in case Gogs starts in SSH mode.
+ Debug = false
+ Prefix = "[git-module] "
+)
+
+func log(format string, args ...interface{}) {
+ if !Debug {
+ return
+ }
+
+ fmt.Print(Prefix)
+ if len(args) == 0 {
+ fmt.Println(format)
+ } else {
+ fmt.Printf(format+"\n", args...)
+ }
+}
+
+var gitVersion string
+
+// Version returns current Git version from shell.
+func BinVersion() (string, error) {
+ if len(gitVersion) > 0 {
+ return gitVersion, nil
+ }
+
+ stdout, err := NewCommand("version").Run()
+ if err != nil {
+ return "", err
+ }
+
+ fields := strings.Fields(stdout)
+ if len(fields) < 3 {
+ return "", fmt.Errorf("not enough output: %s", stdout)
+ }
+
+ // Handle special case on Windows.
+ i := strings.Index(fields[2], "windows")
+ if i >= 1 {
+ gitVersion = fields[2][:i-1]
+ return gitVersion, nil
+ }
+
+ gitVersion = fields[2]
+ return gitVersion, nil
+}
+
+func init() {
+ BinVersion()
+}
+
+// Fsck verifies the connectivity and validity of the objects in the database
+func Fsck(repoPath string, timeout time.Duration, args ...string) error {
+ // Make sure timeout makes sense.
+ if timeout <= 0 {
+ timeout = -1
+ }
+ _, err := NewCommand("fsck").AddArguments(args...).RunInDirTimeout(timeout, repoPath)
+ return err
+}
diff --git a/vendor/code.gitea.io/git/hook.go b/vendor/code.gitea.io/git/hook.go
new file mode 100644
index 0000000000..086bf7126d
--- /dev/null
+++ b/vendor/code.gitea.io/git/hook.go
@@ -0,0 +1,121 @@
+// Copyright 2015 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 git
+
+import (
+ "errors"
+ "io/ioutil"
+ "os"
+ "path"
+ "strings"
+
+ "github.com/Unknwon/com"
+)
+
+// hookNames is a list of Git server hooks' name that are supported.
+var hookNames = []string{
+ "pre-receive",
+ // "update",
+ "post-receive",
+}
+
+var (
+ ErrNotValidHook = errors.New("not a valid Git hook")
+)
+
+// IsValidHookName returns true if given name is a valid Git hook.
+func IsValidHookName(name string) bool {
+ for _, hn := range hookNames {
+ if hn == name {
+ return true
+ }
+ }
+ return false
+}
+
+// Hook represents a Git hook.
+type Hook struct {
+ name string
+ IsActive bool // Indicates whether repository has this hook.
+ Content string // Content of hook if it's active.
+ Sample string // Sample content from Git.
+ path string // Hook file path.
+}
+
+// GetHook returns a Git hook by given name and repository.
+func GetHook(repoPath, name string) (*Hook, error) {
+ if !IsValidHookName(name) {
+ return nil, ErrNotValidHook
+ }
+ h := &Hook{
+ name: name,
+ path: path.Join(repoPath, "hooks", name),
+ }
+ if isFile(h.path) {
+ data, err := ioutil.ReadFile(h.path)
+ if err != nil {
+ return nil, err
+ }
+ h.IsActive = true
+ h.Content = string(data)
+ } else if isFile(h.path + ".sample") {
+ data, err := ioutil.ReadFile(h.path + ".sample")
+ if err != nil {
+ return nil, err
+ }
+ h.Sample = string(data)
+ }
+ return h, nil
+}
+
+func (h *Hook) Name() string {
+ return h.name
+}
+
+// Update updates hook settings.
+func (h *Hook) Update() error {
+ if len(strings.TrimSpace(h.Content)) == 0 {
+ if isExist(h.path) {
+ return os.Remove(h.path)
+ }
+ return nil
+ }
+ return ioutil.WriteFile(h.path, []byte(strings.Replace(h.Content, "\r", "", -1)), os.ModePerm)
+}
+
+// ListHooks returns a list of Git hooks of given repository.
+func ListHooks(repoPath string) (_ []*Hook, err error) {
+ if !isDir(path.Join(repoPath, "hooks")) {
+ return nil, errors.New("hooks path does not exist")
+ }
+
+ hooks := make([]*Hook, len(hookNames))
+ for i, name := range hookNames {
+ hooks[i], err = GetHook(repoPath, name)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return hooks, nil
+}
+
+const (
+ HookPathUpdate = "hooks/update"
+)
+
+// SetUpdateHook writes given content to update hook of the reposiotry.
+func SetUpdateHook(repoPath, content string) (err error) {
+ log("Setting update hook: %s", repoPath)
+ hookPath := path.Join(repoPath, HookPathUpdate)
+ if com.IsExist(hookPath) {
+ err = os.Remove(hookPath)
+ } else {
+ err = os.MkdirAll(path.Dir(hookPath), os.ModePerm)
+ }
+ if err != nil {
+ return err
+ }
+ return ioutil.WriteFile(hookPath, []byte(content), 0777)
+}
diff --git a/vendor/code.gitea.io/git/repo.go b/vendor/code.gitea.io/git/repo.go
new file mode 100644
index 0000000000..bfc2cbe7c8
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo.go
@@ -0,0 +1,193 @@
+// Copyright 2015 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 git
+
+import (
+ "bytes"
+ "container/list"
+ "errors"
+ "os"
+ "path"
+ "path/filepath"
+ "time"
+)
+
+// Repository represents a Git repository.
+type Repository struct {
+ Path string
+
+ commitCache *objectCache
+ tagCache *objectCache
+}
+
+const _PRETTY_LOG_FORMAT = `--pretty=format:%H`
+
+func (repo *Repository) parsePrettyFormatLogToList(logs []byte) (*list.List, error) {
+ l := list.New()
+ if len(logs) == 0 {
+ return l, nil
+ }
+
+ parts := bytes.Split(logs, []byte{'\n'})
+
+ for _, commitId := range parts {
+ commit, err := repo.GetCommit(string(commitId))
+ if err != nil {
+ return nil, err
+ }
+ l.PushBack(commit)
+ }
+
+ return l, nil
+}
+
+// IsRepoURLAccessible checks if given repository URL is accessible.
+func IsRepoURLAccessible(url string) bool {
+ _, err := NewCommand("ls-remote", "-q", "-h", url, "HEAD").Run()
+ if err != nil {
+ return false
+ }
+ return true
+}
+
+// InitRepository initializes a new Git repository.
+func InitRepository(repoPath string, bare bool) error {
+ os.MkdirAll(repoPath, os.ModePerm)
+
+ cmd := NewCommand("init")
+ if bare {
+ cmd.AddArguments("--bare")
+ }
+ _, err := cmd.RunInDir(repoPath)
+ return err
+}
+
+// OpenRepository opens the repository at the given path.
+func OpenRepository(repoPath string) (*Repository, error) {
+ repoPath, err := filepath.Abs(repoPath)
+ if err != nil {
+ return nil, err
+ } else if !isDir(repoPath) {
+ return nil, errors.New("no such file or directory")
+ }
+
+ return &Repository{
+ Path: repoPath,
+ commitCache: newObjectCache(),
+ tagCache: newObjectCache(),
+ }, nil
+}
+
+type CloneRepoOptions struct {
+ Timeout time.Duration
+ Mirror bool
+ Bare bool
+ Quiet bool
+ Branch string
+}
+
+// Clone clones original repository to target path.
+func Clone(from, to string, opts CloneRepoOptions) (err error) {
+ toDir := path.Dir(to)
+ if err = os.MkdirAll(toDir, os.ModePerm); err != nil {
+ return err
+ }
+
+ cmd := NewCommand("clone")
+ if opts.Mirror {
+ cmd.AddArguments("--mirror")
+ }
+ if opts.Bare {
+ cmd.AddArguments("--bare")
+ }
+ if opts.Quiet {
+ cmd.AddArguments("--quiet")
+ }
+ if len(opts.Branch) > 0 {
+ cmd.AddArguments("-b", opts.Branch)
+ }
+ cmd.AddArguments(from, to)
+
+ if opts.Timeout <= 0 {
+ opts.Timeout = -1
+ }
+
+ _, err = cmd.RunTimeout(opts.Timeout)
+ return err
+}
+
+type PullRemoteOptions struct {
+ Timeout time.Duration
+ All bool
+ Remote string
+ Branch string
+}
+
+// Pull pulls changes from remotes.
+func Pull(repoPath string, opts PullRemoteOptions) error {
+ cmd := NewCommand("pull")
+ if opts.All {
+ cmd.AddArguments("--all")
+ } else {
+ cmd.AddArguments(opts.Remote)
+ cmd.AddArguments(opts.Branch)
+ }
+
+ if opts.Timeout <= 0 {
+ opts.Timeout = -1
+ }
+
+ _, err := cmd.RunInDirTimeout(opts.Timeout, repoPath)
+ return err
+}
+
+// Push pushs local commits to given remote branch.
+func Push(repoPath, remote, branch string) error {
+ _, err := NewCommand("push", remote, branch).RunInDir(repoPath)
+ return err
+}
+
+type CheckoutOptions struct {
+ Timeout time.Duration
+ Branch string
+ OldBranch string
+}
+
+// Checkout checkouts a branch
+func Checkout(repoPath string, opts CheckoutOptions) error {
+ cmd := NewCommand("checkout")
+ if len(opts.OldBranch) > 0 {
+ cmd.AddArguments("-b")
+ }
+
+ if opts.Timeout <= 0 {
+ opts.Timeout = -1
+ }
+
+ cmd.AddArguments(opts.Branch)
+
+ if len(opts.OldBranch) > 0 {
+ cmd.AddArguments(opts.OldBranch)
+ }
+
+ _, err := cmd.RunInDirTimeout(opts.Timeout, repoPath)
+ return err
+}
+
+// ResetHEAD resets HEAD to given revision or head of branch.
+func ResetHEAD(repoPath string, hard bool, revision string) error {
+ cmd := NewCommand("reset")
+ if hard {
+ cmd.AddArguments("--hard")
+ }
+ _, err := cmd.AddArguments(revision).RunInDir(repoPath)
+ return err
+}
+
+// MoveFile moves a file to another file or directory.
+func MoveFile(repoPath, oldTreeName, newTreeName string) error {
+ _, err := NewCommand("mv").AddArguments(oldTreeName, newTreeName).RunInDir(repoPath)
+ return err
+}
diff --git a/vendor/code.gitea.io/git/repo_branch.go b/vendor/code.gitea.io/git/repo_branch.go
new file mode 100644
index 0000000000..f7252bb0e9
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo_branch.go
@@ -0,0 +1,119 @@
+// Copyright 2015 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 git
+
+import (
+ "fmt"
+ "strings"
+
+ "github.com/mcuadros/go-version"
+)
+
+const BRANCH_PREFIX = "refs/heads/"
+
+// IsReferenceExist returns true if given reference exists in the repository.
+func IsReferenceExist(repoPath, name string) bool {
+ _, err := NewCommand("show-ref", "--verify", name).RunInDir(repoPath)
+ return err == nil
+}
+
+// IsBranchExist returns true if given branch exists in the repository.
+func IsBranchExist(repoPath, name string) bool {
+ return IsReferenceExist(repoPath, BRANCH_PREFIX+name)
+}
+
+func (repo *Repository) IsBranchExist(name string) bool {
+ return IsBranchExist(repo.Path, name)
+}
+
+// Branch represents a Git branch.
+type Branch struct {
+ Name string
+ Path string
+}
+
+// GetHEADBranch returns corresponding branch of HEAD.
+func (repo *Repository) GetHEADBranch() (*Branch, error) {
+ stdout, err := NewCommand("symbolic-ref", "HEAD").RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ stdout = strings.TrimSpace(stdout)
+
+ if !strings.HasPrefix(stdout, BRANCH_PREFIX) {
+ return nil, fmt.Errorf("invalid HEAD branch: %v", stdout)
+ }
+
+ return &Branch{
+ Name: stdout[len(BRANCH_PREFIX):],
+ Path: stdout,
+ }, nil
+}
+
+// SetDefaultBranch sets default branch of repository.
+func (repo *Repository) SetDefaultBranch(name string) error {
+ if version.Compare(gitVersion, "1.7.10", "<") {
+ return ErrUnsupportedVersion{"1.7.10"}
+ }
+
+ _, err := NewCommand("symbolic-ref", "HEAD", BRANCH_PREFIX+name).RunInDir(repo.Path)
+ return err
+}
+
+// GetBranches returns all branches of the repository.
+func (repo *Repository) GetBranches() ([]string, error) {
+ stdout, err := NewCommand("show-ref", "--heads").RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ infos := strings.Split(stdout, "\n")
+ branches := make([]string, len(infos)-1)
+ for i, info := range infos[:len(infos)-1] {
+ fields := strings.Fields(info)
+ if len(fields) != 2 {
+ continue // NOTE: I should believe git will not give me wrong string.
+ }
+ branches[i] = strings.TrimPrefix(fields[1], BRANCH_PREFIX)
+ }
+ return branches, nil
+}
+
+// Option(s) for delete branch
+type DeleteBranchOptions struct {
+ Force bool
+}
+
+// DeleteBranch delete a branch by name on repository.
+func (repo *Repository) DeleteBranch(name string, opts DeleteBranchOptions) error {
+ cmd := NewCommand("branch", "-d")
+
+ if opts.Force {
+ cmd.AddArguments("-f")
+ }
+
+ cmd.AddArguments(name)
+ _, err := cmd.RunInDir(repo.Path)
+
+ return err
+}
+
+// AddRemote adds a new remote to repository.
+func (repo *Repository) AddRemote(name, url string, fetch bool) error {
+ cmd := NewCommand("remote", "add")
+ if fetch {
+ cmd.AddArguments("-f")
+ }
+ cmd.AddArguments(name, url)
+
+ _, err := cmd.RunInDir(repo.Path)
+ return err
+}
+
+// RemoveRemote removes a remote from repository.
+func (repo *Repository) RemoveRemote(name string) error {
+ _, err := NewCommand("remote", "remove", name).RunInDir(repo.Path)
+ return err
+}
diff --git a/vendor/code.gitea.io/git/repo_commit.go b/vendor/code.gitea.io/git/repo_commit.go
new file mode 100644
index 0000000000..1e7e51a8f2
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo_commit.go
@@ -0,0 +1,353 @@
+// Copyright 2015 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 git
+
+import (
+ "bytes"
+ "container/list"
+ "fmt"
+ "strconv"
+ "strings"
+
+ "github.com/mcuadros/go-version"
+)
+
+// getRefCommitID returns the last commit ID string of given reference (branch or tag).
+func (repo *Repository) getRefCommitID(name string) (string, error) {
+ stdout, err := NewCommand("show-ref", "--verify", name).RunInDir(repo.Path)
+ if err != nil {
+ if strings.Contains(err.Error(), "not a valid ref") {
+ return "", ErrNotExist{name, ""}
+ }
+ return "", err
+ }
+ return strings.Split(stdout, " ")[0], nil
+}
+
+// GetBranchCommitID returns last commit ID string of given branch.
+func (repo *Repository) GetBranchCommitID(name string) (string, error) {
+ return repo.getRefCommitID(BRANCH_PREFIX + name)
+}
+
+// GetTagCommitID returns last commit ID string of given tag.
+func (repo *Repository) GetTagCommitID(name string) (string, error) {
+ return repo.getRefCommitID(TAG_PREFIX + name)
+}
+
+// parseCommitData parses commit information from the (uncompressed) raw
+// data from the commit object.
+// \n\n separate headers from message
+func parseCommitData(data []byte) (*Commit, error) {
+ commit := new(Commit)
+ commit.parents = make([]sha1, 0, 1)
+ // we now have the contents of the commit object. Let's investigate...
+ nextline := 0
+l:
+ for {
+ eol := bytes.IndexByte(data[nextline:], '\n')
+ switch {
+ case eol > 0:
+ line := data[nextline : nextline+eol]
+ spacepos := bytes.IndexByte(line, ' ')
+ reftype := line[:spacepos]
+ switch string(reftype) {
+ case "tree", "object":
+ id, err := NewIDFromString(string(line[spacepos+1:]))
+ if err != nil {
+ return nil, err
+ }
+ commit.Tree.ID = id
+ case "parent":
+ // A commit can have one or more parents
+ oid, err := NewIDFromString(string(line[spacepos+1:]))
+ if err != nil {
+ return nil, err
+ }
+ commit.parents = append(commit.parents, oid)
+ case "author", "tagger":
+ sig, err := newSignatureFromCommitline(line[spacepos+1:])
+ if err != nil {
+ return nil, err
+ }
+ commit.Author = sig
+ case "committer":
+ sig, err := newSignatureFromCommitline(line[spacepos+1:])
+ if err != nil {
+ return nil, err
+ }
+ commit.Committer = sig
+ }
+ nextline += eol + 1
+ case eol == 0:
+ commit.CommitMessage = string(data[nextline+1:])
+ break l
+ default:
+ break l
+ }
+ }
+ return commit, nil
+}
+
+func (repo *Repository) getCommit(id sha1) (*Commit, error) {
+ c, ok := repo.commitCache.Get(id.String())
+ if ok {
+ log("Hit cache: %s", id)
+ return c.(*Commit), nil
+ }
+
+ data, err := NewCommand("cat-file", "-p", id.String()).RunInDirBytes(repo.Path)
+ if err != nil {
+ if strings.Contains(err.Error(), "fatal: Not a valid object name") {
+ return nil, ErrNotExist{id.String(), ""}
+ }
+ return nil, err
+ }
+
+ commit, err := parseCommitData(data)
+ if err != nil {
+ return nil, err
+ }
+ commit.repo = repo
+ commit.ID = id
+
+ repo.commitCache.Set(id.String(), commit)
+ return commit, nil
+}
+
+// GetCommit returns commit object of by ID string.
+func (repo *Repository) GetCommit(commitID string) (*Commit, error) {
+ if len(commitID) != 40 {
+ var err error
+ commitID, err = NewCommand("rev-parse", commitID).RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ }
+ id, err := NewIDFromString(commitID)
+ if err != nil {
+ return nil, err
+ }
+
+ return repo.getCommit(id)
+}
+
+// GetBranchCommit returns the last commit of given branch.
+func (repo *Repository) GetBranchCommit(name string) (*Commit, error) {
+ commitID, err := repo.GetBranchCommitID(name)
+ if err != nil {
+ return nil, err
+ }
+ return repo.GetCommit(commitID)
+}
+
+func (repo *Repository) GetTagCommit(name string) (*Commit, error) {
+ commitID, err := repo.GetTagCommitID(name)
+ if err != nil {
+ return nil, err
+ }
+ return repo.GetCommit(commitID)
+}
+
+func (repo *Repository) getCommitByPathWithID(id sha1, relpath string) (*Commit, error) {
+ // File name starts with ':' must be escaped.
+ if relpath[0] == ':' {
+ relpath = `\` + relpath
+ }
+
+ stdout, err := NewCommand("log", "-1", _PRETTY_LOG_FORMAT, id.String(), "--", relpath).RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ id, err = NewIDFromString(stdout)
+ if err != nil {
+ return nil, err
+ }
+
+ return repo.getCommit(id)
+}
+
+// GetCommitByPath returns the last commit of relative path.
+func (repo *Repository) GetCommitByPath(relpath string) (*Commit, error) {
+ stdout, err := NewCommand("log", "-1", _PRETTY_LOG_FORMAT, "--", relpath).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ commits, err := repo.parsePrettyFormatLogToList(stdout)
+ if err != nil {
+ return nil, err
+ }
+ return commits.Front().Value.(*Commit), nil
+}
+
+var CommitsRangeSize = 50
+
+func (repo *Repository) commitsByRange(id sha1, page int) (*list.List, error) {
+ stdout, err := NewCommand("log", id.String(), "--skip="+strconv.Itoa((page-1)*CommitsRangeSize),
+ "--max-count="+strconv.Itoa(CommitsRangeSize), _PRETTY_LOG_FORMAT).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ return repo.parsePrettyFormatLogToList(stdout)
+}
+
+func (repo *Repository) searchCommits(id sha1, keyword string) (*list.List, error) {
+ stdout, err := NewCommand("log", id.String(), "-100", "-i", "--grep="+keyword, _PRETTY_LOG_FORMAT).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ return repo.parsePrettyFormatLogToList(stdout)
+}
+
+func (repo *Repository) getFilesChanged(id1 string, id2 string) ([]string, error) {
+ stdout, err := NewCommand("diff", "--name-only", id1, id2).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ return strings.Split(string(stdout), "\n"), nil
+}
+
+func (repo *Repository) FileCommitsCount(revision, file string) (int64, error) {
+ return commitsCount(repo.Path, revision, file)
+}
+
+func (repo *Repository) CommitsByFileAndRange(revision, file string, page int) (*list.List, error) {
+ stdout, err := NewCommand("log", revision, "--skip="+strconv.Itoa((page-1)*50),
+ "--max-count="+strconv.Itoa(CommitsRangeSize), _PRETTY_LOG_FORMAT, "--", file).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ return repo.parsePrettyFormatLogToList(stdout)
+}
+
+func (repo *Repository) FilesCountBetween(startCommitID, endCommitID string) (int, error) {
+ stdout, err := NewCommand("diff", "--name-only", startCommitID+"..."+endCommitID).RunInDir(repo.Path)
+ if err != nil {
+ return 0, err
+ }
+ return len(strings.Split(stdout, "\n")) - 1, nil
+}
+
+// CommitsBetween returns a list that contains commits between [last, before).
+func (repo *Repository) CommitsBetween(last *Commit, before *Commit) (*list.List, error) {
+ if version.Compare(gitVersion, "1.8.0", ">=") {
+ stdout, err := NewCommand("rev-list", before.ID.String()+"..."+last.ID.String()).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ return repo.parsePrettyFormatLogToList(bytes.TrimSpace(stdout))
+ }
+
+ // Fallback to stupid solution, which iterates all commits of the repository
+ // if before is not an ancestor of last.
+ l := list.New()
+ if last == nil || last.ParentCount() == 0 {
+ return l, nil
+ }
+
+ var err error
+ cur := last
+ for {
+ if cur.ID.Equal(before.ID) {
+ break
+ }
+ l.PushBack(cur)
+ if cur.ParentCount() == 0 {
+ break
+ }
+ cur, err = cur.Parent(0)
+ if err != nil {
+ return nil, err
+ }
+ }
+ return l, nil
+}
+
+func (repo *Repository) CommitsBetweenIDs(last, before string) (*list.List, error) {
+ lastCommit, err := repo.GetCommit(last)
+ if err != nil {
+ return nil, err
+ }
+ beforeCommit, err := repo.GetCommit(before)
+ if err != nil {
+ return nil, err
+ }
+ return repo.CommitsBetween(lastCommit, beforeCommit)
+}
+
+func (repo *Repository) CommitsCountBetween(start, end string) (int64, error) {
+ return commitsCount(repo.Path, start+"..."+end, "")
+}
+
+// The limit is depth, not total number of returned commits.
+func (repo *Repository) commitsBefore(l *list.List, parent *list.Element, id sha1, current, limit int) error {
+ // Reach the limit
+ if limit > 0 && current > limit {
+ return nil
+ }
+
+ commit, err := repo.getCommit(id)
+ if err != nil {
+ return fmt.Errorf("getCommit: %v", err)
+ }
+
+ var e *list.Element
+ if parent == nil {
+ e = l.PushBack(commit)
+ } else {
+ var in = parent
+ for {
+ if in == nil {
+ break
+ } else if in.Value.(*Commit).ID.Equal(commit.ID) {
+ return nil
+ } else if in.Next() == nil {
+ break
+ }
+
+ if in.Value.(*Commit).Committer.When.Equal(commit.Committer.When) {
+ break
+ }
+
+ if in.Value.(*Commit).Committer.When.After(commit.Committer.When) &&
+ in.Next().Value.(*Commit).Committer.When.Before(commit.Committer.When) {
+ break
+ }
+
+ in = in.Next()
+ }
+
+ e = l.InsertAfter(commit, in)
+ }
+
+ pr := parent
+ if commit.ParentCount() > 1 {
+ pr = e
+ }
+
+ for i := 0; i < commit.ParentCount(); i++ {
+ id, err := commit.ParentID(i)
+ if err != nil {
+ return err
+ }
+ err = repo.commitsBefore(l, pr, id, current+1, limit)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (repo *Repository) getCommitsBefore(id sha1) (*list.List, error) {
+ l := list.New()
+ return l, repo.commitsBefore(l, nil, id, 1, 0)
+}
+
+func (repo *Repository) getCommitsBeforeLimit(id sha1, num int) (*list.List, error) {
+ l := list.New()
+ return l, repo.commitsBefore(l, nil, id, 1, num)
+}
diff --git a/vendor/code.gitea.io/git/repo_hook.go b/vendor/code.gitea.io/git/repo_hook.go
new file mode 100644
index 0000000000..7b49647e3c
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo_hook.go
@@ -0,0 +1,13 @@
+// Copyright 2015 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 git
+
+func (repo *Repository) GetHook(name string) (*Hook, error) {
+ return GetHook(repo.Path, name)
+}
+
+func (repo *Repository) Hooks() ([]*Hook, error) {
+ return ListHooks(repo.Path)
+}
diff --git a/vendor/code.gitea.io/git/repo_object.go b/vendor/code.gitea.io/git/repo_object.go
new file mode 100644
index 0000000000..416ee4591a
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo_object.go
@@ -0,0 +1,14 @@
+// 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 git
+
+type ObjectType string
+
+const (
+ OBJECT_COMMIT ObjectType = "commit"
+ OBJECT_TREE ObjectType = "tree"
+ OBJECT_BLOB ObjectType = "blob"
+ OBJECT_TAG ObjectType = "tag"
+)
diff --git a/vendor/code.gitea.io/git/repo_pull.go b/vendor/code.gitea.io/git/repo_pull.go
new file mode 100644
index 0000000000..1b0c1cf432
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo_pull.go
@@ -0,0 +1,75 @@
+// Copyright 2015 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 git
+
+import (
+ "container/list"
+ "fmt"
+ "strconv"
+ "strings"
+ "time"
+)
+
+// PullRequestInfo represents needed information for a pull request.
+type PullRequestInfo struct {
+ MergeBase string
+ Commits *list.List
+ NumFiles int
+}
+
+// GetMergeBase checks and returns merge base of two branches.
+func (repo *Repository) GetMergeBase(base, head string) (string, error) {
+ stdout, err := NewCommand("merge-base", base, head).RunInDir(repo.Path)
+ return strings.TrimSpace(stdout), err
+}
+
+// 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) {
+ var remoteBranch string
+
+ // We don't need a temporary remote for same repository.
+ if repo.Path != basePath {
+ // Add a temporary remote
+ tmpRemote := strconv.FormatInt(time.Now().UnixNano(), 10)
+ if err = repo.AddRemote(tmpRemote, basePath, true); err != nil {
+ return nil, fmt.Errorf("AddRemote: %v", err)
+ }
+ defer repo.RemoveRemote(tmpRemote)
+
+ remoteBranch = "remotes/" + tmpRemote + "/" + baseBranch
+ } else {
+ remoteBranch = baseBranch
+ }
+
+ prInfo := new(PullRequestInfo)
+ prInfo.MergeBase, err = repo.GetMergeBase(remoteBranch, headBranch)
+ if err != nil {
+ return nil, fmt.Errorf("GetMergeBase: %v", err)
+ }
+
+ logs, err := NewCommand("log", prInfo.MergeBase+"..."+headBranch, _PRETTY_LOG_FORMAT).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ prInfo.Commits, err = repo.parsePrettyFormatLogToList(logs)
+ if err != nil {
+ return nil, fmt.Errorf("parsePrettyFormatLogToList: %v", err)
+ }
+
+ // Count number of changed files.
+ stdout, err := NewCommand("diff", "--name-only", remoteBranch+"..."+headBranch).RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ prInfo.NumFiles = len(strings.Split(stdout, "\n")) - 1
+
+ return prInfo, nil
+}
+
+// GetPatch generates and returns patch data between given revisions.
+func (repo *Repository) GetPatch(base, head string) ([]byte, error) {
+ return NewCommand("diff", "-p", "--binary", base, head).RunInDirBytes(repo.Path)
+}
diff --git a/vendor/code.gitea.io/git/repo_tag.go b/vendor/code.gitea.io/git/repo_tag.go
new file mode 100644
index 0000000000..b69bbf8b37
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo_tag.go
@@ -0,0 +1,120 @@
+// Copyright 2015 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 git
+
+import (
+ "strings"
+
+ "github.com/mcuadros/go-version"
+)
+
+const TAG_PREFIX = "refs/tags/"
+
+// IsTagExist returns true if given tag exists in the repository.
+func IsTagExist(repoPath, name string) bool {
+ return IsReferenceExist(repoPath, TAG_PREFIX+name)
+}
+
+func (repo *Repository) IsTagExist(name string) bool {
+ return IsTagExist(repo.Path, name)
+}
+
+func (repo *Repository) CreateTag(name, revision string) error {
+ _, err := NewCommand("tag", name, revision).RunInDir(repo.Path)
+ return err
+}
+
+func (repo *Repository) getTag(id sha1) (*Tag, error) {
+ t, ok := repo.tagCache.Get(id.String())
+ if ok {
+ log("Hit cache: %s", id)
+ return t.(*Tag), nil
+ }
+
+ // Get tag type
+ tp, err := NewCommand("cat-file", "-t", id.String()).RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ tp = strings.TrimSpace(tp)
+
+ // Tag is a commit.
+ if ObjectType(tp) == OBJECT_COMMIT {
+ tag := &Tag{
+ ID: id,
+ Object: id,
+ Type: string(OBJECT_COMMIT),
+ repo: repo,
+ }
+
+ repo.tagCache.Set(id.String(), tag)
+ return tag, nil
+ }
+
+ // Tag with message.
+ data, err := NewCommand("cat-file", "-p", id.String()).RunInDirBytes(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ tag, err := parseTagData(data)
+ if err != nil {
+ return nil, err
+ }
+
+ tag.ID = id
+ tag.repo = repo
+
+ repo.tagCache.Set(id.String(), tag)
+ return tag, nil
+}
+
+// GetTag returns a Git tag by given name.
+func (repo *Repository) GetTag(name string) (*Tag, error) {
+ stdout, err := NewCommand("show-ref", "--tags", name).RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ 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 = name
+ return tag, nil
+}
+
+// GetTags returns all tags of the repository.
+func (repo *Repository) GetTags() ([]string, error) {
+ cmd := NewCommand("tag", "-l")
+ if version.Compare(gitVersion, "2.0.0", ">=") {
+ cmd.AddArguments("--sort=-v:refname")
+ }
+
+ stdout, err := cmd.RunInDir(repo.Path)
+ if err != nil {
+ return nil, err
+ }
+
+ tags := strings.Split(stdout, "\n")
+ tags = tags[:len(tags)-1]
+
+ if version.Compare(gitVersion, "2.0.0", "<") {
+ version.Sort(tags)
+
+ // Reverse order
+ for i := 0; i < len(tags) / 2; i++ {
+ j := len(tags) - i - 1
+ tags[i], tags[j] = tags[j], tags[i]
+ }
+ }
+
+ return tags, nil
+}
diff --git a/vendor/code.gitea.io/git/repo_tree.go b/vendor/code.gitea.io/git/repo_tree.go
new file mode 100644
index 0000000000..baebb25101
--- /dev/null
+++ b/vendor/code.gitea.io/git/repo_tree.go
@@ -0,0 +1,26 @@
+// Copyright 2015 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 git
+
+func (repo *Repository) getTree(id sha1) (*Tree, error) {
+ treePath := filepathFromSHA1(repo.Path, id.String())
+ if isFile(treePath) {
+ _, err := NewCommand("ls-tree", id.String()).RunInDir(repo.Path)
+ if err != nil {
+ return nil, ErrNotExist{id.String(), ""}
+ }
+ }
+
+ return NewTree(repo, id), nil
+}
+
+// Find the tree object in the repository.
+func (repo *Repository) GetTree(idStr string) (*Tree, error) {
+ id, err := NewIDFromString(idStr)
+ if err != nil {
+ return nil, err
+ }
+ return repo.getTree(id)
+}
diff --git a/vendor/code.gitea.io/git/sha1.go b/vendor/code.gitea.io/git/sha1.go
new file mode 100644
index 0000000000..7744275d85
--- /dev/null
+++ b/vendor/code.gitea.io/git/sha1.go
@@ -0,0 +1,93 @@
+// Copyright 2015 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 git
+
+import (
+ "encoding/hex"
+ "fmt"
+ "strings"
+)
+
+const EMPTY_SHA = "0000000000000000000000000000000000000000"
+
+type sha1 [20]byte
+
+// Equal returns true if s has the same sha1 as caller.
+// Support 40-length-string, []byte, sha1.
+func (id sha1) Equal(s2 interface{}) bool {
+ switch v := s2.(type) {
+ case string:
+ if len(v) != 40 {
+ return false
+ }
+ return v == id.String()
+ case []byte:
+ if len(v) != 20 {
+ return false
+ }
+ for i, v := range v {
+ if id[i] != v {
+ return false
+ }
+ }
+ case sha1:
+ for i, v := range v {
+ if id[i] != v {
+ return false
+ }
+ }
+ default:
+ return false
+ }
+ return true
+}
+
+// String returns string (hex) representation of the Oid.
+func (s sha1) String() string {
+ result := make([]byte, 0, 40)
+ hexvalues := []byte("0123456789abcdef")
+ for i := 0; i < 20; i++ {
+ result = append(result, hexvalues[s[i]>>4])
+ result = append(result, hexvalues[s[i]&0xf])
+ }
+ return string(result)
+}
+
+// MustID always creates a new sha1 from a [20]byte array with no validation of input.
+func MustID(b []byte) sha1 {
+ var id sha1
+ for i := 0; i < 20; i++ {
+ id[i] = b[i]
+ }
+ return id
+}
+
+// NewID creates a new sha1 from a [20]byte array.
+func NewID(b []byte) (sha1, error) {
+ if len(b) != 20 {
+ return sha1{}, fmt.Errorf("Length must be 20: %v", b)
+ }
+ return MustID(b), nil
+}
+
+// MustIDFromString always creates a new sha from a ID with no validation of input.
+func MustIDFromString(s string) sha1 {
+ b, _ := hex.DecodeString(s)
+ return MustID(b)
+}
+
+// NewIDFromString creates a new sha1 from a ID string of length 40.
+func NewIDFromString(s string) (sha1, error) {
+ var id sha1
+ s = strings.TrimSpace(s)
+ if len(s) != 40 {
+ return id, fmt.Errorf("Length must be 40: %s", s)
+ }
+ b, err := hex.DecodeString(s)
+ if err != nil {
+ return id, err
+ }
+ return NewID(b)
+}
diff --git a/vendor/code.gitea.io/git/signature.go b/vendor/code.gitea.io/git/signature.go
new file mode 100644
index 0000000000..95eb1bbe07
--- /dev/null
+++ b/vendor/code.gitea.io/git/signature.go
@@ -0,0 +1,48 @@
+// Copyright 2015 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 git
+
+import (
+ "bytes"
+ "strconv"
+ "time"
+)
+
+// Signature represents the Author or Committer information.
+type Signature struct {
+ Email string
+ Name string
+ When time.Time
+}
+
+// Helper to get a signature from the commit line, which looks like these:
+// author Patrick Gundlach <gundlach@speedata.de> 1378823654 +0200
+// author Patrick Gundlach <gundlach@speedata.de> Thu, 07 Apr 2005 22:13:13 +0200
+// but without the "author " at the beginning (this method should)
+// be used for author and committer.
+//
+// FIXME: include timezone for timestamp!
+func newSignatureFromCommitline(line []byte) (_ *Signature, err error) {
+ sig := new(Signature)
+ emailStart := bytes.IndexByte(line, '<')
+ sig.Name = string(line[:emailStart-1])
+ emailEnd := bytes.IndexByte(line, '>')
+ sig.Email = string(line[emailStart+1 : emailEnd])
+
+ // Check date format.
+ firstChar := line[emailEnd+2]
+ if firstChar >= 48 && firstChar <= 57 {
+ timestop := bytes.IndexByte(line[emailEnd+2:], ' ')
+ timestring := string(line[emailEnd+2 : emailEnd+2+timestop])
+ seconds, _ := strconv.ParseInt(timestring, 10, 64)
+ sig.When = time.Unix(seconds, 0)
+ } else {
+ sig.When, err = time.Parse("Mon Jan _2 15:04:05 2006 -0700", string(line[emailEnd+2:]))
+ if err != nil {
+ return nil, err
+ }
+ }
+ return sig, nil
+}
diff --git a/vendor/code.gitea.io/git/submodule.go b/vendor/code.gitea.io/git/submodule.go
new file mode 100644
index 0000000000..5777330058
--- /dev/null
+++ b/vendor/code.gitea.io/git/submodule.go
@@ -0,0 +1,78 @@
+// Copyright 2015 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 git
+
+import "strings"
+
+type SubModule struct {
+ Name string
+ URL string
+}
+
+// SubModuleFile represents a file with submodule type.
+type SubModuleFile struct {
+ *Commit
+
+ refURL string
+ refID string
+}
+
+func NewSubModuleFile(c *Commit, refURL, refID string) *SubModuleFile {
+ return &SubModuleFile{
+ Commit: c,
+ refURL: refURL,
+ refID: refID,
+ }
+}
+
+// RefURL guesses and returns reference URL.
+func (sf *SubModuleFile) RefURL(urlPrefix string, parentPath string) string {
+ if sf.refURL == "" {
+ return ""
+ }
+
+ url := strings.TrimSuffix(sf.refURL, ".git")
+
+ // git://xxx/user/repo
+ if strings.HasPrefix(url, "git://") {
+ return "http://" + strings.TrimPrefix(url, "git://")
+ }
+
+ // http[s]://xxx/user/repo
+ if strings.HasPrefix(url, "http://") || strings.HasPrefix(url, "https://") {
+ return url
+ }
+
+ // Relative url prefix check (according to git submodule documentation)
+ if strings.HasPrefix(url, "./") || strings.HasPrefix(url, "../") {
+ // ...construct and return correct submodule url here...
+ idx := strings.Index(parentPath, "/src/")
+ if idx == -1 {
+ return url
+ }
+ return strings.TrimSuffix(urlPrefix, "/") + parentPath[:idx] + "/" + url
+ }
+
+ // sysuser@xxx:user/repo
+ i := strings.Index(url, "@")
+ j := strings.LastIndex(url, ":")
+
+ // Only process when i < j because git+ssh://git@git.forwardbias.in/npploader.git
+ if i > -1 && j > -1 && i < j {
+ // fix problem with reverse proxy works only with local server
+ if strings.Contains(urlPrefix, url[i+1:j]) {
+ return urlPrefix + url[j+1:]
+ } else {
+ return "http://" + url[i+1:j] + "/" + url[j+1:]
+ }
+ }
+
+ return url
+}
+
+// RefID returns reference ID.
+func (sf *SubModuleFile) RefID() string {
+ return sf.refID
+}
diff --git a/vendor/code.gitea.io/git/tag.go b/vendor/code.gitea.io/git/tag.go
new file mode 100644
index 0000000000..f4bf77925f
--- /dev/null
+++ b/vendor/code.gitea.io/git/tag.go
@@ -0,0 +1,65 @@
+// Copyright 2015 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 git
+
+import "bytes"
+
+// Tag represents a Git tag.
+type Tag struct {
+ Name string
+ ID sha1
+ repo *Repository
+ Object sha1 // The id of this commit object
+ Type string
+ Tagger *Signature
+ Message string
+}
+
+func (tag *Tag) Commit() (*Commit, error) {
+ return tag.repo.getCommit(tag.Object)
+}
+
+// Parse commit information from the (uncompressed) raw
+// data from the commit object.
+// \n\n separate headers from message
+func parseTagData(data []byte) (*Tag, error) {
+ tag := new(Tag)
+ // we now have the contents of the commit object. Let's investigate...
+ nextline := 0
+l:
+ for {
+ eol := bytes.IndexByte(data[nextline:], '\n')
+ switch {
+ case eol > 0:
+ line := data[nextline : nextline+eol]
+ spacepos := bytes.IndexByte(line, ' ')
+ reftype := line[:spacepos]
+ switch string(reftype) {
+ case "object":
+ id, err := NewIDFromString(string(line[spacepos+1:]))
+ if err != nil {
+ return nil, err
+ }
+ tag.Object = id
+ case "type":
+ // A commit can have one or more parents
+ tag.Type = string(line[spacepos+1:])
+ case "tagger":
+ sig, err := newSignatureFromCommitline(line[spacepos+1:])
+ if err != nil {
+ return nil, err
+ }
+ tag.Tagger = sig
+ }
+ nextline += eol + 1
+ case eol == 0:
+ tag.Message = string(data[nextline+1:])
+ break l
+ default:
+ break l
+ }
+ }
+ return tag, nil
+}
diff --git a/vendor/code.gitea.io/git/tree.go b/vendor/code.gitea.io/git/tree.go
new file mode 100644
index 0000000000..8704282efd
--- /dev/null
+++ b/vendor/code.gitea.io/git/tree.go
@@ -0,0 +1,151 @@
+// Copyright 2015 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 git
+
+import (
+ "bytes"
+ "fmt"
+ "strings"
+)
+
+// Tree represents a flat directory listing.
+type Tree struct {
+ ID sha1
+ repo *Repository
+
+ // parent tree
+ ptree *Tree
+
+ entries Entries
+ entriesParsed bool
+}
+
+func NewTree(repo *Repository, id sha1) *Tree {
+ return &Tree{
+ ID: id,
+ repo: repo,
+ }
+}
+
+var escapeChar = []byte("\\")
+
+// UnescapeChars reverses escaped characters.
+func UnescapeChars(in []byte) []byte {
+ if bytes.Index(in, escapeChar) == -1 {
+ return in
+ }
+
+ endIdx := len(in) - 1
+ isEscape := false
+ out := make([]byte, 0, endIdx+1)
+ for i := range in {
+ if in[i] == '\\' && !isEscape {
+ isEscape = true
+ continue
+ }
+ isEscape = false
+ out = append(out, in[i])
+ }
+ return out
+}
+
+// parseTreeData parses tree information from the (uncompressed) raw
+// data from the tree object.
+func parseTreeData(tree *Tree, data []byte) ([]*TreeEntry, error) {
+ entries := make([]*TreeEntry, 0, 10)
+ l := len(data)
+ pos := 0
+ for pos < l {
+ entry := new(TreeEntry)
+ entry.ptree = tree
+ step := 6
+ switch string(data[pos : pos+step]) {
+ case "100644":
+ entry.mode = ENTRY_MODE_BLOB
+ entry.Type = OBJECT_BLOB
+ case "100755":
+ entry.mode = ENTRY_MODE_EXEC
+ entry.Type = OBJECT_BLOB
+ case "120000":
+ entry.mode = ENTRY_MODE_SYMLINK
+ entry.Type = OBJECT_BLOB
+ case "160000":
+ entry.mode = ENTRY_MODE_COMMIT
+ entry.Type = OBJECT_COMMIT
+
+ step = 8
+ case "040000":
+ entry.mode = ENTRY_MODE_TREE
+ entry.Type = OBJECT_TREE
+ default:
+ return nil, fmt.Errorf("unknown type: %v", string(data[pos:pos+step]))
+ }
+ pos += step + 6 // Skip string type of entry type.
+
+ step = 40
+ id, err := NewIDFromString(string(data[pos : pos+step]))
+ if err != nil {
+ return nil, err
+ }
+ entry.ID = id
+ pos += step + 1 // Skip half of sha1.
+
+ step = bytes.IndexByte(data[pos:], '\n')
+
+ // In case entry name is surrounded by double quotes(it happens only in git-shell).
+ if data[pos] == '"' {
+ entry.name = string(UnescapeChars(data[pos+1 : pos+step-1]))
+ } else {
+ entry.name = string(data[pos : pos+step])
+ }
+
+ pos += step + 1
+ entries = append(entries, entry)
+ }
+ return entries, nil
+}
+
+func (t *Tree) SubTree(rpath string) (*Tree, error) {
+ if len(rpath) == 0 {
+ return t, nil
+ }
+
+ paths := strings.Split(rpath, "/")
+ var (
+ err error
+ g = t
+ p = t
+ te *TreeEntry
+ )
+ for _, name := range paths {
+ te, err = p.GetTreeEntryByPath(name)
+ if err != nil {
+ return nil, err
+ }
+
+ g, err = t.repo.getTree(te.ID)
+ if err != nil {
+ return nil, err
+ }
+ g.ptree = p
+ p = g
+ }
+ return g, nil
+}
+
+// ListEntries returns all entries of current tree.
+func (t *Tree) ListEntries() (Entries, error) {
+ if t.entriesParsed {
+ return t.entries, nil
+ }
+ t.entriesParsed = true
+
+ stdout, err := NewCommand("ls-tree", t.ID.String()).RunInDirBytes(t.repo.Path)
+ if err != nil {
+ return nil, err
+ }
+ t.entries, err = parseTreeData(t, stdout)
+ return t.entries, err
+}
diff --git a/vendor/code.gitea.io/git/tree_blob.go b/vendor/code.gitea.io/git/tree_blob.go
new file mode 100644
index 0000000000..e2e701521f
--- /dev/null
+++ b/vendor/code.gitea.io/git/tree_blob.go
@@ -0,0 +1,57 @@
+// Copyright 2015 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 git
+
+import (
+ "path"
+ "strings"
+)
+
+func (t *Tree) GetTreeEntryByPath(relpath string) (*TreeEntry, error) {
+ if len(relpath) == 0 {
+ return &TreeEntry{
+ ID: t.ID,
+ Type: OBJECT_TREE,
+ mode: ENTRY_MODE_TREE,
+ }, nil
+ }
+
+ relpath = path.Clean(relpath)
+ parts := strings.Split(relpath, "/")
+ var err error
+ tree := t
+ for i, name := range parts {
+ if i == len(parts)-1 {
+ entries, err := tree.ListEntries()
+ if err != nil {
+ return nil, err
+ }
+ for _, v := range entries {
+ if v.name == name {
+ return v, nil
+ }
+ }
+ } else {
+ tree, err = tree.SubTree(name)
+ if err != nil {
+ return nil, err
+ }
+ }
+ }
+ return nil, ErrNotExist{"", relpath}
+}
+
+func (t *Tree) GetBlobByPath(relpath string) (*Blob, error) {
+ entry, err := t.GetTreeEntryByPath(relpath)
+ if err != nil {
+ return nil, err
+ }
+
+ if !entry.IsDir() {
+ return entry.Blob(), nil
+ }
+
+ return nil, ErrNotExist{"", relpath}
+}
diff --git a/vendor/code.gitea.io/git/tree_entry.go b/vendor/code.gitea.io/git/tree_entry.go
new file mode 100644
index 0000000000..1c9e89d70c
--- /dev/null
+++ b/vendor/code.gitea.io/git/tree_entry.go
@@ -0,0 +1,209 @@
+// Copyright 2015 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 git
+
+import (
+ "fmt"
+ "path"
+ "path/filepath"
+ "sort"
+ "strconv"
+ "strings"
+ "time"
+)
+
+type EntryMode int
+
+// There are only a few file modes in Git. They look like unix file modes, but they can only be
+// one of these.
+const (
+ ENTRY_MODE_BLOB EntryMode = 0100644
+ ENTRY_MODE_EXEC EntryMode = 0100755
+ ENTRY_MODE_SYMLINK EntryMode = 0120000
+ ENTRY_MODE_COMMIT EntryMode = 0160000
+ ENTRY_MODE_TREE EntryMode = 0040000
+)
+
+type TreeEntry struct {
+ ID sha1
+ Type ObjectType
+
+ mode EntryMode
+ name string
+
+ ptree *Tree
+
+ commited bool
+
+ size int64
+ sized bool
+}
+
+func (te *TreeEntry) Name() string {
+ return te.name
+}
+
+func (te *TreeEntry) Size() int64 {
+ if te.IsDir() {
+ return 0
+ } else if te.sized {
+ return te.size
+ }
+
+ stdout, err := NewCommand("cat-file", "-s", te.ID.String()).RunInDir(te.ptree.repo.Path)
+ if err != nil {
+ return 0
+ }
+
+ te.sized = true
+ te.size, _ = strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
+ return te.size
+}
+
+func (te *TreeEntry) IsSubModule() bool {
+ return te.mode == ENTRY_MODE_COMMIT
+}
+
+func (te *TreeEntry) IsDir() bool {
+ return te.mode == ENTRY_MODE_TREE
+}
+
+func (te *TreeEntry) Blob() *Blob {
+ return &Blob{
+ repo: te.ptree.repo,
+ TreeEntry: te,
+ }
+}
+
+type Entries []*TreeEntry
+
+var sorter = []func(t1, t2 *TreeEntry) bool{
+ func(t1, t2 *TreeEntry) bool {
+ return (t1.IsDir() || t1.IsSubModule()) && !t2.IsDir() && !t2.IsSubModule()
+ },
+ func(t1, t2 *TreeEntry) bool {
+ return t1.name < t2.name
+ },
+}
+
+func (tes Entries) Len() int { return len(tes) }
+func (tes Entries) Swap(i, j int) { tes[i], tes[j] = tes[j], tes[i] }
+func (tes Entries) Less(i, j int) bool {
+ t1, t2 := tes[i], tes[j]
+ var k int
+ for k = 0; k < len(sorter)-1; k++ {
+ sort := sorter[k]
+ switch {
+ case sort(t1, t2):
+ return true
+ case sort(t2, t1):
+ return false
+ }
+ }
+ return sorter[k](t1, t2)
+}
+
+func (tes Entries) Sort() {
+ sort.Sort(tes)
+}
+
+type commitInfo struct {
+ entryName string
+ infos []interface{}
+ err error
+}
+
+// GetCommitsInfo takes advantages of concurrey to speed up getting information
+// of all commits that are corresponding to these entries.
+// TODO: limit max goroutines number should be configurable
+func (tes Entries) GetCommitsInfo(commit *Commit, treePath string) ([][]interface{}, error) {
+ if len(tes) == 0 {
+ return nil, nil
+ }
+
+ // Length of taskChan determines how many goroutines (subprocesses) can run at the same time.
+ // The length of revChan should be same as taskChan so goroutines whoever finished job can
+ // exit as early as possible, only store data inside channel.
+ taskChan := make(chan bool, 10)
+ revChan := make(chan commitInfo, 10)
+ doneChan := make(chan error)
+
+ // Receive loop will exit when it collects same number of data pieces as tree entries.
+ // It notifies doneChan before exits or notify early with possible error.
+ infoMap := make(map[string][]interface{}, len(tes))
+ go func() {
+ i := 0
+ for info := range revChan {
+ if info.err != nil {
+ doneChan <- info.err
+ return
+ }
+
+ infoMap[info.entryName] = info.infos
+ i++
+ if i == len(tes) {
+ break
+ }
+ }
+ doneChan <- nil
+ }()
+
+ for i := range tes {
+ // When taskChan is idle (or has empty slots), put operation will not block.
+ // However when taskChan is full, code will block and wait any running goroutines to finish.
+ taskChan <- true
+
+ if tes[i].Type != OBJECT_COMMIT {
+ go func(i int) {
+ time.Sleep(200 * time.Millisecond)
+ cinfo := commitInfo{entryName: tes[i].Name()}
+ c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
+ if err != nil {
+ cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
+ } else {
+ cinfo.infos = []interface{}{tes[i], c}
+ }
+ revChan <- cinfo
+ <-taskChan // Clear one slot from taskChan to allow new goroutines to start.
+ }(i)
+ continue
+ }
+
+ // Handle submodule
+ go func(i int) {
+ cinfo := commitInfo{entryName: tes[i].Name()}
+ sm, err := commit.GetSubModule(path.Join(treePath, tes[i].Name()))
+ if err != nil && !IsErrNotExist(err) {
+ cinfo.err = fmt.Errorf("GetSubModule (%s/%s): %v", treePath, tes[i].Name(), err)
+ revChan <- cinfo
+ return
+ }
+
+ smURL := ""
+ if sm != nil {
+ smURL = sm.URL
+ }
+
+ c, err := commit.GetCommitByPath(filepath.Join(treePath, tes[i].Name()))
+ if err != nil {
+ cinfo.err = fmt.Errorf("GetCommitByPath (%s/%s): %v", treePath, tes[i].Name(), err)
+ } else {
+ cinfo.infos = []interface{}{tes[i], NewSubModuleFile(c, smURL, tes[i].ID.String())}
+ }
+ revChan <- cinfo
+ <-taskChan
+ }(i)
+ }
+
+ if err := <-doneChan; err != nil {
+ return nil, err
+ }
+
+ commitsInfo := make([][]interface{}, len(tes))
+ for i := 0; i < len(tes); i++ {
+ commitsInfo[i] = infoMap[tes[i].Name()]
+ }
+ return commitsInfo, nil
+}
diff --git a/vendor/code.gitea.io/git/utlis.go b/vendor/code.gitea.io/git/utlis.go
new file mode 100644
index 0000000000..da8c58170e
--- /dev/null
+++ b/vendor/code.gitea.io/git/utlis.go
@@ -0,0 +1,93 @@
+// Copyright 2015 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 git
+
+import (
+ "fmt"
+ "os"
+ "path/filepath"
+ "strings"
+ "sync"
+)
+
+// objectCache provides thread-safe cache opeations.
+type objectCache struct {
+ lock sync.RWMutex
+ cache map[string]interface{}
+}
+
+func newObjectCache() *objectCache {
+ return &objectCache{
+ cache: make(map[string]interface{}, 10),
+ }
+}
+
+func (oc *objectCache) Set(id string, obj interface{}) {
+ oc.lock.Lock()
+ defer oc.lock.Unlock()
+
+ oc.cache[id] = obj
+}
+
+func (oc *objectCache) Get(id string) (interface{}, bool) {
+ oc.lock.RLock()
+ defer oc.lock.RUnlock()
+
+ obj, has := oc.cache[id]
+ return obj, has
+}
+
+// isDir returns true if given path is a directory,
+// or returns false when it's a file or does not exist.
+func isDir(dir string) bool {
+ f, e := os.Stat(dir)
+ if e != nil {
+ return false
+ }
+ return f.IsDir()
+}
+
+// isFile returns true if given path is a file,
+// or returns false when it's a directory or does not exist.
+func isFile(filePath string) bool {
+ f, e := os.Stat(filePath)
+ if e != nil {
+ return false
+ }
+ return !f.IsDir()
+}
+
+// isExist checks whether a file or directory exists.
+// It returns false when the file or directory does not exist.
+func isExist(path string) bool {
+ _, err := os.Stat(path)
+ return err == nil || os.IsExist(err)
+}
+
+func concatenateError(err error, stderr string) error {
+ if len(stderr) == 0 {
+ return err
+ }
+ return fmt.Errorf("%v - %s", err, stderr)
+}
+
+// If the object is stored in its own file (i.e not in a pack file),
+// this function returns the full path to the object file.
+// It does not test if the file exists.
+func filepathFromSHA1(rootdir, sha1 string) string {
+ return filepath.Join(rootdir, "objects", sha1[:2], sha1[2:])
+}
+
+func RefEndName(refStr string) string {
+ if strings.HasPrefix(refStr, BRANCH_PREFIX) {
+ return refStr[len(BRANCH_PREFIX):]
+ }
+
+ if strings.HasPrefix(refStr, TAG_PREFIX) {
+ return refStr[len(TAG_PREFIX):]
+ }
+
+ return refStr
+}
diff --git a/vendor/code.gitea.io/go-sdk/LICENSE b/vendor/code.gitea.io/go-sdk/LICENSE
new file mode 100644
index 0000000000..10aeba46bc
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2016 The Gitea Authors
+Copyright (c) 2014 The Gogs Authors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/vendor/code.gitea.io/go-sdk/gitea/admin_org.go b/vendor/code.gitea.io/go-sdk/gitea/admin_org.go
new file mode 100644
index 0000000000..520fa12990
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/admin_org.go
@@ -0,0 +1,21 @@
+// Copyright 2015 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+func (c *Client) AdminCreateOrg(user string, opt CreateOrgOption) (*Organization, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ org := new(Organization)
+ return org, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/orgs", user),
+ jsonHeader, bytes.NewReader(body), org)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/admin_repo.go b/vendor/code.gitea.io/go-sdk/gitea/admin_repo.go
new file mode 100644
index 0000000000..06daa94597
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/admin_repo.go
@@ -0,0 +1,21 @@
+// Copyright 2015 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+func (c *Client) AdminCreateRepo(user string, opt CreateRepoOption) (*Repository, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/repos", user),
+ jsonHeader, bytes.NewReader(body), repo)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/admin_user.go b/vendor/code.gitea.io/go-sdk/gitea/admin_user.go
new file mode 100644
index 0000000000..186008b77b
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/admin_user.go
@@ -0,0 +1,68 @@
+// Copyright 2015 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type CreateUserOption struct {
+ SourceID int64 `json:"source_id"`
+ LoginName string `json:"login_name"`
+ Username string `json:"username" binding:"Required;AlphaDashDot;MaxSize(35)"`
+ FullName string `json:"full_name" binding:"MaxSize(100)"`
+ Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
+ Password string `json:"password" binding:"MaxSize(255)"`
+ SendNotify bool `json:"send_notify"`
+}
+
+func (c *Client) AdminCreateUser(opt CreateUserOption) (*User, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ user := new(User)
+ return user, c.getParsedResponse("POST", "/admin/users", jsonHeader, bytes.NewReader(body), user)
+}
+
+type EditUserOption struct {
+ SourceID int64 `json:"source_id"`
+ LoginName string `json:"login_name"`
+ FullName string `json:"full_name" binding:"MaxSize(100)"`
+ Email string `json:"email" binding:"Required;Email;MaxSize(254)"`
+ Password string `json:"password" binding:"MaxSize(255)"`
+ Website string `json:"website" binding:"MaxSize(50)"`
+ Location string `json:"location" binding:"MaxSize(50)"`
+ Active *bool `json:"active"`
+ Admin *bool `json:"admin"`
+ AllowGitHook *bool `json:"allow_git_hook"`
+ AllowImportLocal *bool `json:"allow_import_local"`
+ MaxRepoCreation *int `json:"max_repo_creation"`
+}
+
+func (c *Client) AdminEditUser(user string, opt EditUserOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/admin/users/%s", user), jsonHeader, bytes.NewReader(body))
+ return err
+}
+
+func (c *Client) AdminDeleteUser(user string) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/admin/users/%s", user), nil, nil)
+ return err
+}
+
+func (c *Client) AdminCreateUserPublicKey(user string, opt CreateKeyOption) (*PublicKey, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ key := new(PublicKey)
+ return key, c.getParsedResponse("POST", fmt.Sprintf("/admin/users/%s/keys", user), jsonHeader, bytes.NewReader(body), key)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/gitea.go b/vendor/code.gitea.io/go-sdk/gitea/gitea.go
new file mode 100644
index 0000000000..0a6bf4d749
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/gitea.go
@@ -0,0 +1,90 @@
+// 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 gitea
+
+import (
+ "encoding/json"
+ "errors"
+ "io"
+ "io/ioutil"
+ "net/http"
+ "strings"
+)
+
+func Version() string {
+ return "0.12.3"
+}
+
+// Client represents a Gogs API client.
+type Client struct {
+ url string
+ accessToken string
+ client *http.Client
+}
+
+// NewClient initializes and returns a API client.
+func NewClient(url, token string) *Client {
+ return &Client{
+ url: strings.TrimSuffix(url, "/"),
+ accessToken: token,
+ client: &http.Client{},
+ }
+}
+
+// SetHTTPClient replaces default http.Client with user given one.
+func (c *Client) SetHTTPClient(client *http.Client) {
+ c.client = client
+}
+
+func (c *Client) doRequest(method, path string, header http.Header, body io.Reader) (*http.Response, error) {
+ req, err := http.NewRequest(method, c.url+"/api/v1"+path, body)
+ if err != nil {
+ return nil, err
+ }
+ req.Header.Set("Authorization", "token "+c.accessToken)
+ for k, v := range header {
+ req.Header[k] = v
+ }
+
+ return c.client.Do(req)
+}
+
+func (c *Client) getResponse(method, path string, header http.Header, body io.Reader) ([]byte, error) {
+ resp, err := c.doRequest(method, path, header, body)
+ if err != nil {
+ return nil, err
+ }
+ defer resp.Body.Close()
+
+ data, err := ioutil.ReadAll(resp.Body)
+ if err != nil {
+ return nil, err
+ }
+
+ switch resp.StatusCode {
+ case 403:
+ return nil, errors.New("403 Forbidden")
+ case 404:
+ return nil, errors.New("404 Not Found")
+ }
+
+ if resp.StatusCode/100 != 2 {
+ errMap := make(map[string]interface{})
+ if err = json.Unmarshal(data, &errMap); err != nil {
+ return nil, err
+ }
+ return nil, errors.New(errMap["message"].(string))
+ }
+
+ return data, nil
+}
+
+func (c *Client) getParsedResponse(method, path string, header http.Header, body io.Reader, obj interface{}) error {
+ data, err := c.getResponse(method, path, header, body)
+ if err != nil {
+ return err
+ }
+ return json.Unmarshal(data, obj)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/issue.go b/vendor/code.gitea.io/go-sdk/gitea/issue.go
new file mode 100644
index 0000000000..4392e00004
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/issue.go
@@ -0,0 +1,92 @@
+// Copyright 2016 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type StateType string
+
+const (
+ STATE_OPEN StateType = "open"
+ STATE_CLOSED StateType = "closed"
+)
+
+type PullRequestMeta struct {
+ HasMerged bool `json:"merged"`
+ Merged *time.Time `json:"merged_at"`
+}
+
+type Issue struct {
+ ID int64 `json:"id"`
+ Index int64 `json:"number"`
+ Poster *User `json:"user"`
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Labels []*Label `json:"labels"`
+ Milestone *Milestone `json:"milestone"`
+ Assignee *User `json:"assignee"`
+ State StateType `json:"state"`
+ Comments int `json:"comments"`
+ Created time.Time `json:"created_at"`
+ Updated time.Time `json:"updated_at"`
+
+ PullRequest *PullRequestMeta `json:"pull_request"`
+}
+
+type ListIssueOption struct {
+ Page int
+}
+
+func (c *Client) ListRepoIssues(owner, repo string, opt ListIssueOption) ([]*Issue, error) {
+ issues := make([]*Issue, 0, 10)
+ return issues, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues?page=%d", owner, repo, opt.Page), nil, nil, &issues)
+}
+
+func (c *Client) GetIssue(owner, repo string, index int64) (*Issue, error) {
+ issue := new(Issue)
+ return issue, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index), nil, nil, issue)
+}
+
+type CreateIssueOption struct {
+ Title string `json:"title" binding:"Required"`
+ Body string `json:"body"`
+ Assignee string `json:"assignee"`
+ Milestone int64 `json:"milestone"`
+ Labels []int64 `json:"labels"`
+ Closed bool `json:"closed"`
+}
+
+func (c *Client) CreateIssue(owner, repo string, opt CreateIssueOption) (*Issue, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ issue := new(Issue)
+ return issue, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues", owner, repo),
+ jsonHeader, bytes.NewReader(body), issue)
+}
+
+type EditIssueOption struct {
+ Title string `json:"title"`
+ Body *string `json:"body"`
+ Assignee *string `json:"assignee"`
+ Milestone *int64 `json:"milestone"`
+ State *string `json:"state"`
+}
+
+func (c *Client) EditIssue(owner, repo string, index int64, opt EditIssueOption) (*Issue, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ issue := new(Issue)
+ return issue, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/issues/%d", owner, repo, index),
+ jsonHeader, bytes.NewReader(body), issue)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/issue_comment.go b/vendor/code.gitea.io/go-sdk/gitea/issue_comment.go
new file mode 100644
index 0000000000..59f064a8ad
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/issue_comment.go
@@ -0,0 +1,57 @@
+// Copyright 2016 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+// Comment represents a comment in commit and issue page.
+type Comment struct {
+ ID int64 `json:"id"`
+ Poster *User `json:"user"`
+ Body string `json:"body"`
+ Created time.Time `json:"created_at"`
+ Updated time.Time `json:"updated_at"`
+}
+
+// ListIssueComments list comments on an issue.
+func (c *Client) ListIssueComments(owner, repo string, index int64) ([]*Comment, error) {
+ comments := make([]*Comment, 0, 10)
+ return comments, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/comments", owner, repo, index), nil, nil, &comments)
+}
+
+// CreateIssueCommentOption is option when creating an issue comment.
+type CreateIssueCommentOption struct {
+ Body string `json:"body" binding:"Required"`
+}
+
+// CreateIssueComment create comment on an issue.
+func (c *Client) CreateIssueComment(owner, repo string, index int64, opt CreateIssueCommentOption) (*Comment, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ comment := new(Comment)
+ return comment, c.getParsedResponse("POST", fmt.Sprintf("/repos/:%s/:%s/issues/%d/comments", owner, repo, index), jsonHeader, bytes.NewReader(body), comment)
+}
+
+// EditIssueCommentOption is option when editing an issue comment.
+type EditIssueCommentOption struct {
+ Body string `json:"body" binding:"Required"`
+}
+
+// EditIssueComment edits an issue comment.
+func (c *Client) EditIssueComment(owner, repo string, index, commentID int64, opt EditIssueCommentOption) (*Comment, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ comment := new(Comment)
+ return comment, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/:%s/:%s/issues/%d/comments/%d", owner, repo, index, commentID), jsonHeader, bytes.NewReader(body), comment)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/issue_label.go b/vendor/code.gitea.io/go-sdk/gitea/issue_label.go
new file mode 100644
index 0000000000..681e504c34
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/issue_label.go
@@ -0,0 +1,98 @@
+// Copyright 2016 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type Label struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ Color string `json:"color"`
+}
+
+func (c *Client) ListRepoLabels(owner, repo string) ([]*Label, error) {
+ labels := make([]*Label, 0, 10)
+ return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels", owner, repo), nil, nil, &labels)
+}
+
+func (c *Client) GetRepoLabel(owner, repo string, id int64) (*Label, error) {
+ label := new(Label)
+ return label, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil, label)
+}
+
+type CreateLabelOption struct {
+ Name string `json:"name" binding:"Required"`
+ Color string `json:"color" binding:"Required;Size(7)"`
+}
+
+func (c *Client) CreateLabel(owner, repo string, opt CreateLabelOption) (*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ label := new(Label)
+ return label, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/labels", owner, repo),
+ jsonHeader, bytes.NewReader(body), label)
+}
+
+type EditLabelOption struct {
+ Name *string `json:"name"`
+ Color *string `json:"color"`
+}
+
+func (c *Client) EditLabel(owner, repo string, id int64, opt EditLabelOption) (*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ label := new(Label)
+ return label, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), label)
+}
+
+func (c *Client) DeleteLabel(owner, repo string, id int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/labels/%d", owner, repo, id), nil, nil)
+ return err
+}
+
+type IssueLabelsOption struct {
+ Labels []int64 `json:"labels"`
+}
+
+func (c *Client) GetIssueLabels(owner, repo string, index int64) ([]*Label, error) {
+ labels := make([]*Label, 0, 5)
+ return labels, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil, &labels)
+}
+
+func (c *Client) AddIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ labels := make([]*Label, 0)
+ return labels, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
+}
+
+func (c *Client) ReplaceIssueLabels(owner, repo string, index int64, opt IssueLabelsOption) ([]*Label, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ labels := make([]*Label, 0)
+ return labels, c.getParsedResponse("PUT", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), jsonHeader, bytes.NewReader(body), &labels)
+}
+
+func (c *Client) DeleteIssueLabel(owner, repo string, index, label int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels/%d", owner, repo, index, label), nil, nil)
+ return err
+}
+
+func (c *Client) ClearIssueLabels(owner, repo string, index int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/issues/%d/labels", owner, repo, index), nil, nil)
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/issue_milestone.go b/vendor/code.gitea.io/go-sdk/gitea/issue_milestone.go
new file mode 100644
index 0000000000..58f17893a7
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/issue_milestone.go
@@ -0,0 +1,69 @@
+// Copyright 2016 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type Milestone struct {
+ ID int64 `json:"id"`
+ Title string `json:"title"`
+ Description string `json:"description"`
+ State StateType `json:"state"`
+ OpenIssues int `json:"open_issues"`
+ ClosedIssues int `json:"closed_issues"`
+ Closed *time.Time `json:"closed_at"`
+ Deadline *time.Time `json:"due_on"`
+}
+
+func (c *Client) ListRepoMilestones(owner, repo string) ([]*Milestone, error) {
+ milestones := make([]*Milestone, 0, 10)
+ return milestones, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), nil, nil, &milestones)
+}
+
+func (c *Client) GetMilestone(owner, repo string, id int64) (*Milestone, error) {
+ milestone := new(Milestone)
+ return milestone, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil, milestone)
+}
+
+type CreateMilestoneOption struct {
+ Title string `json:"title"`
+ Description string `json:"description"`
+ Deadline *time.Time `json:"due_on"`
+}
+
+func (c *Client) CreateMilestone(owner, repo string, opt CreateMilestoneOption) (*Milestone, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ milestone := new(Milestone)
+ return milestone, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/milestones", owner, repo), jsonHeader, bytes.NewReader(body), milestone)
+}
+
+type EditMilestoneOption struct {
+ Title string `json:"title"`
+ Description *string `json:"description"`
+ State *string `json:"state"`
+ Deadline *time.Time `json:"due_on"`
+}
+
+func (c *Client) EditMilestone(owner, repo string, id int64, opt EditMilestoneOption) (*Milestone, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ milestone := new(Milestone)
+ return milestone, c.getParsedResponse("PATCH", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), jsonHeader, bytes.NewReader(body), milestone)
+}
+
+func (c *Client) DeleteMilestone(owner, repo string, id int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/milestones/%d", owner, repo, id), nil, nil)
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/miscellaneous.go b/vendor/code.gitea.io/go-sdk/gitea/miscellaneous.go
new file mode 100644
index 0000000000..d97940e13c
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/miscellaneous.go
@@ -0,0 +1,11 @@
+// Copyright 2015 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 gitea
+
+type MarkdownOption struct {
+ Text string
+ Mode string
+ Context string
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/org.go b/vendor/code.gitea.io/go-sdk/gitea/org.go
new file mode 100644
index 0000000000..70d872cf51
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/org.go
@@ -0,0 +1,60 @@
+// Copyright 2015 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type Organization struct {
+ ID int64 `json:"id"`
+ UserName string `json:"username"`
+ FullName string `json:"full_name"`
+ AvatarUrl string `json:"avatar_url"`
+ Description string `json:"description"`
+ Website string `json:"website"`
+ Location string `json:"location"`
+}
+
+func (c *Client) ListMyOrgs() ([]*Organization, error) {
+ orgs := make([]*Organization, 0, 5)
+ return orgs, c.getParsedResponse("GET", "/user/orgs", nil, nil, &orgs)
+}
+
+func (c *Client) ListUserOrgs(user string) ([]*Organization, error) {
+ orgs := make([]*Organization, 0, 5)
+ return orgs, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/orgs", user), nil, nil, &orgs)
+}
+
+func (c *Client) GetOrg(orgname string) (*Organization, error) {
+ org := new(Organization)
+ return org, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s", orgname), nil, nil, org)
+}
+
+type CreateOrgOption struct {
+ UserName string `json:"username" binding:"Required"`
+ FullName string `json:"full_name"`
+ Description string `json:"description"`
+ Website string `json:"website"`
+ Location string `json:"location"`
+}
+
+type EditOrgOption struct {
+ FullName string `json:"full_name"`
+ Description string `json:"description"`
+ Website string `json:"website"`
+ Location string `json:"location"`
+}
+
+func (c *Client) EditOrg(orgname string, opt EditOrgOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/orgs/%s", orgname), jsonHeader, bytes.NewReader(body))
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/org_member.go b/vendor/code.gitea.io/go-sdk/gitea/org_member.go
new file mode 100644
index 0000000000..46e839805d
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/org_member.go
@@ -0,0 +1,24 @@
+// Copyright 2016 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type AddOrgMembershipOption struct {
+ Role string `json:"role" binding:"Required"`
+}
+
+func (c *Client) AddOrgMembership(org, user string, opt AddOrgMembershipOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PUT", fmt.Sprintf("/orgs/%s/membership/%s", org, user), jsonHeader, bytes.NewReader(body))
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/org_team.go b/vendor/code.gitea.io/go-sdk/gitea/org_team.go
new file mode 100644
index 0000000000..38da20d997
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/org_team.go
@@ -0,0 +1,18 @@
+// Copyright 2016 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 gitea
+
+type Team struct {
+ ID int64 `json:"id"`
+ Name string `json:"name"`
+ Description string `json:"description"`
+ Permission string `json:"permission"`
+}
+
+type CreateTeamOption struct {
+ Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(30)"`
+ Description string `json:"description" binding:"MaxSize(255)"`
+ Permission string `json:"permission"`
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/pull.go b/vendor/code.gitea.io/go-sdk/gitea/pull.go
new file mode 100644
index 0000000000..efc746388a
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/pull.go
@@ -0,0 +1,37 @@
+// Copyright 2016 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 gitea
+
+import (
+ "time"
+)
+
+// PullRequest represents a pull reqesut API object.
+type PullRequest struct {
+ // Copied from issue.go
+ ID int64 `json:"id"`
+ Index int64 `json:"number"`
+ Poster *User `json:"user"`
+ Title string `json:"title"`
+ Body string `json:"body"`
+ Labels []*Label `json:"labels"`
+ Milestone *Milestone `json:"milestone"`
+ Assignee *User `json:"assignee"`
+ State StateType `json:"state"`
+ Comments int `json:"comments"`
+
+ HeadBranch string `json:"head_branch"`
+ HeadRepo *Repository `json:"head_repo"`
+ BaseBranch string `json:"base_branch"`
+ BaseRepo *Repository `json:"base_repo"`
+
+ HTMLURL string `json:"html_url"`
+
+ Mergeable *bool `json:"mergeable"`
+ HasMerged bool `json:"merged"`
+ Merged *time.Time `json:"merged_at"`
+ MergedCommitID *string `json:"merge_commit_sha"`
+ MergedBy *User `json:"merged_by"`
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/repo.go b/vendor/code.gitea.io/go-sdk/gitea/repo.go
new file mode 100644
index 0000000000..266c01cc92
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/repo.go
@@ -0,0 +1,125 @@
+// 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+// Permission represents a API permission.
+type Permission struct {
+ Admin bool `json:"admin"`
+ Push bool `json:"push"`
+ Pull bool `json:"pull"`
+}
+
+// Repository represents a API repository.
+type Repository struct {
+ ID int64 `json:"id"`
+ Owner *User `json:"owner"`
+ Name string `json:"name"`
+ FullName string `json:"full_name"`
+ Description string `json:"description"`
+ Private bool `json:"private"`
+ Fork bool `json:"fork"`
+ HTMLURL string `json:"html_url"`
+ SSHURL string `json:"ssh_url"`
+ CloneURL string `json:"clone_url"`
+ Website string `json:"website"`
+ Stars int `json:"stars_count"`
+ Forks int `json:"forks_count"`
+ Watchers int `json:"watchers_count"`
+ OpenIssues int `json:"open_issues_count"`
+ DefaultBranch string `json:"default_branch"`
+ Created time.Time `json:"created_at"`
+ Updated time.Time `json:"updated_at"`
+ Permissions *Permission `json:"permissions,omitempty"`
+}
+
+// ListMyRepos lists all repositories for the authenticated user that has access to.
+func (c *Client) ListMyRepos() ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
+ return repos, c.getParsedResponse("GET", "/user/repos", nil, nil, &repos)
+}
+
+func (c *Client) ListUserRepos(user string) ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
+ return repos, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/repos", user), nil, nil, &repos)
+}
+
+func (c *Client) ListOrgRepos(org string) ([]*Repository, error) {
+ repos := make([]*Repository, 0, 10)
+ return repos, c.getParsedResponse("GET", fmt.Sprintf("/orgs/%s/repos", org), nil, nil, &repos)
+}
+
+type CreateRepoOption struct {
+ Name string `json:"name" binding:"Required;AlphaDashDot;MaxSize(100)"`
+ Description string `json:"description" binding:"MaxSize(255)"`
+ Private bool `json:"private"`
+ AutoInit bool `json:"auto_init"`
+ Gitignores string `json:"gitignores"`
+ License string `json:"license"`
+ Readme string `json:"readme"`
+}
+
+// CreateRepo creates a repository for authenticated user.
+func (c *Client) CreateRepo(opt CreateRepoOption) (*Repository, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", "/user/repos", jsonHeader, bytes.NewReader(body), repo)
+}
+
+// CreateOrgRepo creates an organization repository for authenticated user.
+func (c *Client) CreateOrgRepo(org string, opt CreateRepoOption) (*Repository, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", fmt.Sprintf("/org/%s/repos", org), jsonHeader, bytes.NewReader(body), repo)
+}
+
+// GetRepo returns information of a repository of given owner.
+func (c *Client) GetRepo(owner, reponame string) (*Repository, error) {
+ repo := new(Repository)
+ return repo, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s", owner, reponame), nil, nil, repo)
+}
+
+// DeleteRepo deletes a repository of user or organization.
+func (c *Client) DeleteRepo(owner, repo string) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s", owner, repo), nil, nil)
+ return err
+}
+
+type MigrateRepoOption struct {
+ CloneAddr string `json:"clone_addr" binding:"Required"`
+ AuthUsername string `json:"auth_username"`
+ AuthPassword string `json:"auth_password"`
+ UID int `json:"uid" binding:"Required"`
+ RepoName string `json:"repo_name" binding:"Required"`
+ Mirror bool `json:"mirror"`
+ Private bool `json:"private"`
+ Description string `json:"description"`
+}
+
+// MigrateRepo migrates a repository from other Git hosting sources for the
+// authenticated user.
+//
+// To migrate a repository for a organization, the authenticated user must be a
+// owner of the specified organization.
+func (c *Client) MigrateRepo(opt MigrateRepoOption) (*Repository, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ repo := new(Repository)
+ return repo, c.getParsedResponse("POST", "/repos/migrate", jsonHeader, bytes.NewReader(body), repo)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/repo_branch.go b/vendor/code.gitea.io/go-sdk/gitea/repo_branch.go
new file mode 100644
index 0000000000..c57df07c62
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/repo_branch.go
@@ -0,0 +1,25 @@
+// Copyright 2016 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 gitea
+
+import (
+ "fmt"
+)
+
+// Branch represents a repository branch.
+type Branch struct {
+ Name string `json:"name"`
+ Commit *PayloadCommit `json:"commit"`
+}
+
+func (c *Client) ListRepoBranches(user, repo string) ([]*Branch, error) {
+ branches := make([]*Branch, 0, 10)
+ return branches, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches", user, repo), nil, nil, &branches)
+}
+
+func (c *Client) GetRepoBranch(user, repo, branch string) (*Branch, error) {
+ b := new(Branch)
+ return b, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/branches/%s", user, repo, branch), nil, nil, &b)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/repo_collaborator.go b/vendor/code.gitea.io/go-sdk/gitea/repo_collaborator.go
new file mode 100644
index 0000000000..1937de4c0e
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/repo_collaborator.go
@@ -0,0 +1,24 @@
+// Copyright 2016 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+)
+
+type AddCollaboratorOption struct {
+ Permission *string `json:"permission"`
+}
+
+func (c *Client) AddCollaborator(user, repo, collaborator string, opt AddCollaboratorOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PUT", fmt.Sprintf("/repos/%s/%s/collaborators/%s", user, repo, collaborator), nil, bytes.NewReader(body))
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/repo_file.go b/vendor/code.gitea.io/go-sdk/gitea/repo_file.go
new file mode 100644
index 0000000000..e6c89f0c0f
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/repo_file.go
@@ -0,0 +1,15 @@
+// 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 gitea
+
+import (
+ "fmt"
+)
+
+// GetFile downloads a file of repository, ref can be branch/tag/commit.
+// e.g.: ref -> master, tree -> macaron.go(no leading slash)
+func (c *Client) GetFile(user, repo, ref, tree string) ([]byte, error) {
+ return c.getResponse("GET", fmt.Sprintf("/repos/%s/%s/raw/%s/%s", user, repo, ref, tree), nil, nil)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/repo_hook.go b/vendor/code.gitea.io/go-sdk/gitea/repo_hook.go
new file mode 100644
index 0000000000..01cb254216
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/repo_hook.go
@@ -0,0 +1,245 @@
+// 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+)
+
+var (
+ ErrInvalidReceiveHook = errors.New("Invalid JSON payload received over webhook")
+)
+
+type Hook struct {
+ ID int64 `json:"id"`
+ Type string `json:"type"`
+ URL string `json:"-"`
+ Config map[string]string `json:"config"`
+ Events []string `json:"events"`
+ Active bool `json:"active"`
+ Updated time.Time `json:"updated_at"`
+ Created time.Time `json:"created_at"`
+}
+
+func (c *Client) ListRepoHooks(user, repo string) ([]*Hook, error) {
+ hooks := make([]*Hook, 0, 10)
+ return hooks, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), nil, nil, &hooks)
+}
+
+type CreateHookOption struct {
+ Type string `json:"type" binding:"Required"`
+ Config map[string]string `json:"config" binding:"Required"`
+ Events []string `json:"events"`
+ Active bool `json:"active"`
+}
+
+func (c *Client) CreateRepoHook(user, repo string, opt CreateHookOption) (*Hook, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ h := new(Hook)
+ return h, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/hooks", user, repo), jsonHeader, bytes.NewReader(body), h)
+}
+
+type EditHookOption struct {
+ Config map[string]string `json:"config"`
+ Events []string `json:"events"`
+ Active *bool `json:"active"`
+}
+
+func (c *Client) EditRepoHook(user, repo string, id int64, opt EditHookOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("PATCH", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), jsonHeader, bytes.NewReader(body))
+ return err
+}
+
+func (c *Client) DeleteRepoHook(user, repo string, id int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/hooks/%d", user, repo, id), nil, nil)
+ return err
+}
+
+type Payloader interface {
+ SetSecret(string)
+ JSONPayload() ([]byte, error)
+}
+
+type PayloadUser struct {
+ Name string `json:"name"`
+ Email string `json:"email"`
+ UserName string `json:"username"`
+}
+
+// FIXME: consider use same format as API when commits API are added.
+type PayloadCommit struct {
+ ID string `json:"id"`
+ Message string `json:"message"`
+ URL string `json:"url"`
+ Author *PayloadUser `json:"author"`
+ Committer *PayloadUser `json:"committer"`
+ Timestamp time.Time `json:"timestamp"`
+}
+
+var (
+ _ Payloader = &CreatePayload{}
+ _ Payloader = &PushPayload{}
+ _ Payloader = &PullRequestPayload{}
+)
+
+// _________ __
+// \_ ___ \_______ ____ _____ _/ |_ ____
+// / \ \/\_ __ \_/ __ \\__ \\ __\/ __ \
+// \ \____| | \/\ ___/ / __ \| | \ ___/
+// \______ /|__| \___ >____ /__| \___ >
+// \/ \/ \/ \/
+
+type CreatePayload struct {
+ Secret string `json:"secret"`
+ Ref string `json:"ref"`
+ RefType string `json:"ref_type"`
+ Repo *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *CreatePayload) SetSecret(secret string) {
+ p.Secret = secret
+}
+
+func (p *CreatePayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// ParseCreateHook parses create event hook content.
+func ParseCreateHook(raw []byte) (*CreatePayload, error) {
+ hook := new(CreatePayload)
+ if err := json.Unmarshal(raw, hook); err != nil {
+ return nil, err
+ }
+
+ // it is possible the JSON was parsed, however,
+ // was not from Gogs (maybe was from Bitbucket)
+ // So we'll check to be sure certain key fields
+ // were populated
+ switch {
+ case hook.Repo == nil:
+ return nil, ErrInvalidReceiveHook
+ case len(hook.Ref) == 0:
+ return nil, ErrInvalidReceiveHook
+ }
+ return hook, nil
+}
+
+// __________ .__
+// \______ \__ __ _____| |__
+// | ___/ | \/ ___/ | \
+// | | | | /\___ \| Y \
+// |____| |____//____ >___| /
+// \/ \/
+
+// PushPayload represents a payload information of push event.
+type PushPayload struct {
+ Secret string `json:"secret"`
+ Ref string `json:"ref"`
+ Before string `json:"before"`
+ After string `json:"after"`
+ CompareURL string `json:"compare_url"`
+ Commits []*PayloadCommit `json:"commits"`
+ Repo *Repository `json:"repository"`
+ Pusher *User `json:"pusher"`
+ Sender *User `json:"sender"`
+}
+
+func (p *PushPayload) SetSecret(secret string) {
+ p.Secret = secret
+}
+
+func (p *PushPayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
+
+// ParsePushHook parses push event hook content.
+func ParsePushHook(raw []byte) (*PushPayload, error) {
+ hook := new(PushPayload)
+ if err := json.Unmarshal(raw, hook); err != nil {
+ return nil, err
+ }
+
+ switch {
+ case hook.Repo == nil:
+ return nil, ErrInvalidReceiveHook
+ case len(hook.Ref) == 0:
+ return nil, ErrInvalidReceiveHook
+ }
+ return hook, nil
+}
+
+// Branch returns branch name from a payload
+func (p *PushPayload) Branch() string {
+ return strings.Replace(p.Ref, "refs/heads/", "", -1)
+}
+
+// .___
+// | | ______ ________ __ ____
+// | |/ ___// ___/ | \_/ __ \
+// | |\___ \ \___ \| | /\ ___/
+// |___/____ >____ >____/ \___ >
+// \/ \/ \/
+
+type HookIssueAction string
+
+const (
+ HookIssueOpened HookIssueAction = "opened"
+ HookIssueClosed HookIssueAction = "closed"
+ HookIssueReopened HookIssueAction = "reopened"
+ HookIssueEdited HookIssueAction = "edited"
+ HookIssueAssigned HookIssueAction = "assigned"
+ HookIssueUnassigned HookIssueAction = "unassigned"
+ HookIssueLabelUpdated HookIssueAction = "label_updated"
+ HookIssueLabelCleared HookIssueAction = "label_cleared"
+ HookIssueSynchronized HookIssueAction = "synchronized"
+)
+
+type ChangesFromPayload struct {
+ From string `json:"from"`
+}
+
+type ChangesPayload struct {
+ Title *ChangesFromPayload `json:"title,omitempty"`
+ Body *ChangesFromPayload `json:"body,omitempty"`
+}
+
+// __________ .__ .__ __________ __
+// \______ \__ __| | | | \______ \ ____ ________ __ ____ _______/ |_
+// | ___/ | \ | | | | _// __ \/ ____/ | \_/ __ \ / ___/\ __\
+// | | | | / |_| |__ | | \ ___< <_| | | /\ ___/ \___ \ | |
+// |____| |____/|____/____/ |____|_ /\___ >__ |____/ \___ >____ > |__|
+// \/ \/ |__| \/ \/
+
+// PullRequestPayload represents a payload information of pull request event.
+type PullRequestPayload struct {
+ Secret string `json:"secret"`
+ Action HookIssueAction `json:"action"`
+ Index int64 `json:"number"`
+ Changes *ChangesPayload `json:"changes,omitempty"`
+ PullRequest *PullRequest `json:"pull_request"`
+ Repository *Repository `json:"repository"`
+ Sender *User `json:"sender"`
+}
+
+func (p *PullRequestPayload) SetSecret(secret string) {
+ p.Secret = secret
+}
+
+func (p *PullRequestPayload) JSONPayload() ([]byte, error) {
+ return json.MarshalIndent(p, "", " ")
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/repo_key.go b/vendor/code.gitea.io/go-sdk/gitea/repo_key.go
new file mode 100644
index 0000000000..acae30aa54
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/repo_key.go
@@ -0,0 +1,50 @@
+// Copyright 2015 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type DeployKey struct {
+ ID int64 `json:"id"`
+ Key string `json:"key"`
+ URL string `json:"url"`
+ Title string `json:"title"`
+ Created time.Time `json:"created_at"`
+ ReadOnly bool `json:"read_only"`
+}
+
+func (c *Client) ListDeployKeys(user, repo string) ([]*DeployKey, error) {
+ keys := make([]*DeployKey, 0, 10)
+ return keys, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys", user, repo), nil, nil, &keys)
+}
+
+func (c *Client) GetDeployKey(user, repo string, keyID int64) (*DeployKey, error) {
+ key := new(DeployKey)
+ return key, c.getParsedResponse("GET", fmt.Sprintf("/repos/%s/%s/keys/%d", user, repo, keyID), nil, nil, &key)
+}
+
+type CreateKeyOption struct {
+ Title string `json:"title" binding:"Required"`
+ Key string `json:"key" binding:"Required"`
+}
+
+func (c *Client) CreateDeployKey(user, repo string, opt CreateKeyOption) (*DeployKey, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ key := new(DeployKey)
+ return key, c.getParsedResponse("POST", fmt.Sprintf("/repos/%s/%s/keys", user, repo), jsonHeader, bytes.NewReader(body), key)
+}
+
+func (c *Client) DeleteDeployKey(owner, repo string, keyID int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/repos/%s/%s/keys/%d", owner, repo, keyID), nil, nil)
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/user.go b/vendor/code.gitea.io/go-sdk/gitea/user.go
new file mode 100644
index 0000000000..8b78bea941
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/user.go
@@ -0,0 +1,24 @@
+// 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 gitea
+
+import (
+ "fmt"
+)
+
+// User represents a API user.
+type User struct {
+ ID int64 `json:"id"`
+ UserName string `json:"username"`
+ FullName string `json:"full_name"`
+ Email string `json:"email"`
+ AvatarUrl string `json:"avatar_url"`
+}
+
+func (c *Client) GetUserInfo(user string) (*User, error) {
+ u := new(User)
+ err := c.getParsedResponse("GET", fmt.Sprintf("/users/%s", user), nil, nil, u)
+ return u, err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/user_app.go b/vendor/code.gitea.io/go-sdk/gitea/user_app.go
new file mode 100644
index 0000000000..187053bc94
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/user_app.go
@@ -0,0 +1,46 @@
+// 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 gitea
+
+import (
+ "bytes"
+ "encoding/base64"
+ "encoding/json"
+ "fmt"
+ "net/http"
+)
+
+func BasicAuthEncode(user, pass string) string {
+ return base64.StdEncoding.EncodeToString([]byte(user + ":" + pass))
+}
+
+// AccessToken represents a API access token.
+type AccessToken struct {
+ Name string `json:"name"`
+ Sha1 string `json:"sha1"`
+}
+
+func (c *Client) ListAccessTokens(user, pass string) ([]*AccessToken, error) {
+ tokens := make([]*AccessToken, 0, 10)
+ return tokens, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/tokens", user),
+ http.Header{"Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}}, nil, &tokens)
+}
+
+type CreateAccessTokenOption struct {
+ Name string `json:"name" binding:"Required"`
+}
+
+func (c *Client) CreateAccessToken(user, pass string, opt CreateAccessTokenOption) (*AccessToken, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ t := new(AccessToken)
+ return t, c.getParsedResponse("POST", fmt.Sprintf("/users/%s/tokens", user),
+ http.Header{
+ "content-type": []string{"application/json"},
+ "Authorization": []string{"Basic " + BasicAuthEncode(user, pass)}},
+ bytes.NewReader(body), t)
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/user_email.go b/vendor/code.gitea.io/go-sdk/gitea/user_email.go
new file mode 100644
index 0000000000..e9805ecb69
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/user_email.go
@@ -0,0 +1,43 @@
+// Copyright 2015 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+)
+
+type Email struct {
+ Email string `json:"email"`
+ Verified bool `json:"verified"`
+ Primary bool `json:"primary"`
+}
+
+func (c *Client) ListEmails() ([]*Email, error) {
+ emails := make([]*Email, 0, 3)
+ return emails, c.getParsedResponse("GET", "/user/emails", nil, nil, &emails)
+}
+
+type CreateEmailOption struct {
+ Emails []string `json:"emails"`
+}
+
+func (c *Client) AddEmail(opt CreateEmailOption) ([]*Email, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ emails := make([]*Email, 0, 3)
+ return emails, c.getParsedResponse("POST", "/user/emails", jsonHeader, bytes.NewReader(body), emails)
+}
+
+func (c *Client) DeleteEmail(opt CreateEmailOption) error {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return err
+ }
+ _, err = c.getResponse("DELETE", "/user/emails", jsonHeader, bytes.NewReader(body))
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/user_follow.go b/vendor/code.gitea.io/go-sdk/gitea/user_follow.go
new file mode 100644
index 0000000000..cbb2c7b3f3
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/user_follow.go
@@ -0,0 +1,47 @@
+// Copyright 2015 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 gitea
+
+import "fmt"
+
+func (c *Client) ListMyFollowers(page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/user/followers?page=%d", page), nil, nil, &users)
+}
+
+func (c *Client) ListFollowers(user string, page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/followers?page=%d", user, page), nil, nil, &users)
+}
+
+func (c *Client) ListMyFollowing(page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/user/following?page=%d", page), nil, nil, &users)
+}
+
+func (c *Client) ListFollowing(user string, page int) ([]*User, error) {
+ users := make([]*User, 0, 10)
+ return users, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/following?page=%d", user, page), nil, nil, &users)
+}
+
+func (c *Client) IsFollowing(target string) bool {
+ _, err := c.getResponse("GET", fmt.Sprintf("/user/following/%s", target), nil, nil)
+ return err == nil
+}
+
+func (c *Client) IsUserFollowing(user, target string) bool {
+ _, err := c.getResponse("GET", fmt.Sprintf("/users/%s/following/%s", user, target), nil, nil)
+ return err == nil
+}
+
+func (c *Client) Follow(target string) error {
+ _, err := c.getResponse("PUT", fmt.Sprintf("/user/following/%s", target), nil, nil)
+ return err
+}
+
+func (c *Client) Unfollow(target string) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/user/following/%s", target), nil, nil)
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/user_key.go b/vendor/code.gitea.io/go-sdk/gitea/user_key.go
new file mode 100644
index 0000000000..8af5ed7c42
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/user_key.go
@@ -0,0 +1,49 @@
+// Copyright 2015 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 gitea
+
+import (
+ "bytes"
+ "encoding/json"
+ "fmt"
+ "time"
+)
+
+type PublicKey struct {
+ ID int64 `json:"id"`
+ Key string `json:"key"`
+ URL string `json:"url,omitempty"`
+ Title string `json:"title,omitempty"`
+ Created time.Time `json:"created_at,omitempty"`
+}
+
+func (c *Client) ListPublicKeys(user string) ([]*PublicKey, error) {
+ keys := make([]*PublicKey, 0, 10)
+ return keys, c.getParsedResponse("GET", fmt.Sprintf("/users/%s/keys", user), nil, nil, &keys)
+}
+
+func (c *Client) ListMyPublicKeys() ([]*PublicKey, error) {
+ keys := make([]*PublicKey, 0, 10)
+ return keys, c.getParsedResponse("GET", "/user/keys", nil, nil, &keys)
+}
+
+func (c *Client) GetPublicKey(keyID int64) (*PublicKey, error) {
+ key := new(PublicKey)
+ return key, c.getParsedResponse("GET", fmt.Sprintf("/user/keys/%d", keyID), nil, nil, &key)
+}
+
+func (c *Client) CreatePublicKey(opt CreateKeyOption) (*PublicKey, error) {
+ body, err := json.Marshal(&opt)
+ if err != nil {
+ return nil, err
+ }
+ key := new(PublicKey)
+ return key, c.getParsedResponse("POST", "/user/keys", jsonHeader, bytes.NewReader(body), key)
+}
+
+func (c *Client) DeletePublicKey(keyID int64) error {
+ _, err := c.getResponse("DELETE", fmt.Sprintf("/user/keys/%d", keyID), nil, nil)
+ return err
+}
diff --git a/vendor/code.gitea.io/go-sdk/gitea/utils.go b/vendor/code.gitea.io/go-sdk/gitea/utils.go
new file mode 100644
index 0000000000..8d962ba288
--- /dev/null
+++ b/vendor/code.gitea.io/go-sdk/gitea/utils.go
@@ -0,0 +1,23 @@
+// Copyright 2015 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 gitea
+
+import (
+ "net/http"
+)
+
+var jsonHeader = http.Header{"content-type": []string{"application/json"}}
+
+func Bool(v bool) *bool {
+ return &v
+}
+
+func String(v string) *string {
+ return &v
+}
+
+func Int64(v int64) *int64 {
+ return &v
+}