diff options
Diffstat (limited to 'vendor/github.com/gogs/git-module/repo.go')
-rw-r--r-- | vendor/github.com/gogs/git-module/repo.go | 295 |
1 files changed, 295 insertions, 0 deletions
diff --git a/vendor/github.com/gogs/git-module/repo.go b/vendor/github.com/gogs/git-module/repo.go new file mode 100644 index 00000000..ca4805f5 --- /dev/null +++ b/vendor/github.com/gogs/git-module/repo.go @@ -0,0 +1,295 @@ +// 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" + "strings" + "time" + + "github.com/Unknwon/com" +) + +// 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 +} + +type NetworkOptions struct { + URL string + Timeout time.Duration +} + +// IsRepoURLAccessible checks if given repository URL is accessible. +func IsRepoURLAccessible(opts NetworkOptions) bool { + cmd := NewCommand("ls-remote", "-q", "-h", opts.URL, "HEAD") + if opts.Timeout <= 0 { + opts.Timeout = -1 + } + _, err := cmd.RunTimeout(opts.Timeout) + 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 { + Mirror bool + Bare bool + Quiet bool + Branch string + Timeout time.Duration +} + +// 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 FetchRemoteOptions struct { + Prune bool + Timeout time.Duration +} + +// Fetch fetches changes from remotes without merging. +func Fetch(repoPath string, opts FetchRemoteOptions) error { + cmd := NewCommand("fetch") + if opts.Prune { + cmd.AddArguments("--prune") + } + + if opts.Timeout <= 0 { + opts.Timeout = -1 + } + _, err := cmd.RunInDirTimeout(opts.Timeout, repoPath) + return err +} + +type PullRemoteOptions struct { + All bool + Rebase bool + Remote string + Branch string + Timeout time.Duration +} + +// Pull pulls changes from remotes. +func Pull(repoPath string, opts PullRemoteOptions) error { + cmd := NewCommand("pull") + if opts.Rebase { + cmd.AddArguments("--rebase") + } + 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 { + Branch string + OldBranch string + Timeout time.Duration +} + +// Checkout checkouts a branch +func Checkout(repoPath string, opts CheckoutOptions) error { + cmd := NewCommand("checkout") + if len(opts.OldBranch) > 0 { + cmd.AddArguments("-b") + } + + cmd.AddArguments(opts.Branch) + + if len(opts.OldBranch) > 0 { + cmd.AddArguments(opts.OldBranch) + } + if opts.Timeout <= 0 { + opts.Timeout = -1 + } + _, 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 +} + +// CountObject represents disk usage report of Git repository. +type CountObject struct { + Count int64 + Size int64 + InPack int64 + Packs int64 + SizePack int64 + PrunePackable int64 + Garbage int64 + SizeGarbage int64 +} + +const ( + _STAT_COUNT = "count: " + _STAT_SIZE = "size: " + _STAT_IN_PACK = "in-pack: " + _STAT_PACKS = "packs: " + _STAT_SIZE_PACK = "size-pack: " + _STAT_PRUNE_PACKABLE = "prune-packable: " + _STAT_GARBAGE = "garbage: " + _STAT_SIZE_GARBAGE = "size-garbage: " +) + +// GetRepoSize returns disk usage report of repository in given path. +func GetRepoSize(repoPath string) (*CountObject, error) { + cmd := NewCommand("count-objects", "-v") + stdout, err := cmd.RunInDir(repoPath) + if err != nil { + return nil, err + } + + countObject := new(CountObject) + for _, line := range strings.Split(stdout, "\n") { + switch { + case strings.HasPrefix(line, _STAT_COUNT): + countObject.Count = com.StrTo(line[7:]).MustInt64() + case strings.HasPrefix(line, _STAT_SIZE): + countObject.Size = com.StrTo(line[6:]).MustInt64() * 1024 + case strings.HasPrefix(line, _STAT_IN_PACK): + countObject.InPack = com.StrTo(line[9:]).MustInt64() + case strings.HasPrefix(line, _STAT_PACKS): + countObject.Packs = com.StrTo(line[7:]).MustInt64() + case strings.HasPrefix(line, _STAT_SIZE_PACK): + countObject.SizePack = com.StrTo(line[11:]).MustInt64() * 1024 + case strings.HasPrefix(line, _STAT_PRUNE_PACKABLE): + countObject.PrunePackable = com.StrTo(line[16:]).MustInt64() + case strings.HasPrefix(line, _STAT_GARBAGE): + countObject.Garbage = com.StrTo(line[9:]).MustInt64() + case strings.HasPrefix(line, _STAT_SIZE_GARBAGE): + countObject.SizeGarbage = com.StrTo(line[14:]).MustInt64() * 1024 + } + } + + return countObject, nil +} + +// GetLatestCommitDate returns the date of latest commit of repository. +// If branch is empty, it returns the latest commit across all branches. +func GetLatestCommitDate(repoPath, branch string) (time.Time, error) { + cmd := NewCommand("for-each-ref", "--count=1", "--sort=-committerdate", "--format=%(committerdate:iso8601)") + if len(branch) > 0 { + cmd.AddArguments("refs/heads/" + branch) + } + stdout, err := cmd.RunInDir(repoPath) + if err != nil { + return time.Time{}, err + } + + return time.Parse("2006-01-02 15:04:05 -0700", strings.TrimSpace(stdout)) +} |