下面是代码样子,包含添加文件夹及文件,删除文件夹,和commit,push
package ormopt
import (
"strings"
"fmt"
git "gopkg.in/src-d/go-git.v4"
. "gopkg.in/src-d/go-git.v4/_examples"
"gopkg.in/src-d/go-git.v4/plumbing/object"
githttp "gopkg.in/src-d/go-git.v4/plumbing/transport/http"
"io/ioutil"
"os"
"path/filepath"
"github.com/astaxie/beego"
"time"
)
/**
* @author xiaolong.li
* @time 2018-09-10
* @desc 添加文件到本地git库
*/
func GitAddFileAndCmmit (folder string, filePath string, fileName string, fileByte []byte) (error) {
rootPath := beego.AppConfig.String("jksfile.dir")
r, err := git.PlainOpen(rootPath)
if err != nil {
return err
}
w, err := r.Worktree()
if err != nil {
return err
}
directory := rootPath + filePath + "/"
fileDir := directory
exist, err := PathExists(fileDir)
if err != nil {
fmt.Println("PathExists.error:" + err.Error())
}
if !exist { //
err = os.Mkdir(fileDir, os.ModePerm)
if err != nil {
return err
}
}
if folder != "" {
fileDir = directory + folder + "/"
exist, err := PathExists(fileDir)
if err != nil {
fmt.Println("PathExists.error:" + err.Error())
}
if !exist { //
err = os.Mkdir(fileDir, os.ModePerm)
if err != nil {
return err
}
}
}
filename := filepath.Join(fileDir, fileName)
err = ioutil.WriteFile(filename, fileByte, 1024)
if err != nil {
return err
}
// Adds the new file to the staging area.
Info("git add all files= " + filePath + "/")
_, err = w.Add(filePath + "/")
if err != nil {
return err
}
// We can verify the current status of the worktree using the method Status.
Info("git status --porcelain")
_, err = w.Status()
if err != nil {
return err
}
Info("git commit -m \"create git-task commit\"")
commit, err := w.Commit("create git-task commit", &git.CommitOptions{
Author: &object.Signature{
Name: "pass-sys",
Email: "pass-sys",
When: time.Now(),
},
})
if err != nil {
return err
}
// Prints the current HEAD to verify that all worked well.
Info("git show -s")
_, err = r.CommitObject(commit)
//logs.Info(obj.ToString())
if err != nil {
return err
}
return nil
}
/**
* @author xiaolong.li
* @time 2018-09-10
* @desc 删除本地git库中的文件集
*/
func DelGitFiles(directory string) (error) {
path := beego.AppConfig.String("jksfile.dir")
// Opens an already existent repository.
r, err := git.PlainOpen(path)
if err != nil {
return err
}
w, err := r.Worktree()
if err != nil {
return err
}
// del the file to the staging area.
Info("git delete git-file")
_, err = w.Remove(directory + "/")
if err != nil {
return err
}
// We can verify the current status of the worktree using the method Status.
Info("git status --porcelain")
status, err := w.Status()
if err != nil {
return err
}
fmt.Println(status)
// Commits the current staging are to the repository, with the new file
// just created. We should provide the object.Signature of Author of the
// commit.
Info("git commit -am \"delete go-git commit\"")
commit, err := w.Commit("delete go-git commit", &git.CommitOptions{
Author: &object.Signature{
Name: "pass-sys",
Email: "pass-sys",
When: time.Now(),
},
})
if err != nil {
return err
}
// Prints the current HEAD to verify that all worked well.
Info("git show -s")
obj, err := r.CommitObject(commit)
if err != nil {
return err
}
fmt.Println(obj)
return nil
}
/**
* @author xiaolong.li
* @time 2018-09-10
* @desc 删除本地git库中的文件集
*/
func DelGitListFolder (listPath []string) (error) {
path := beego.AppConfig.String("jksfile.dir")
r, err := git.PlainOpen(path)
if err != nil {
return err
}
w, err := r.Worktree()
if err != nil {
return err
}
// del the file to the staging area.
Info("git delete git-file")
for _, filePath := range listPath {
directory := path + filePath + "/"
isExist, err := PathExists(directory)
if err != nil {
fmt.Println("PathExists.error:" + err.Error())
}
if isExist {
_, err = w.Remove(filePath + "/")
if err != nil {
return err
}
}
}
// We can verify the current status of the worktree using the method Status.
Info("git status --porcelain")
_, err = w.Status()
if err != nil {
return err
}
Info("git commit -am \"delete go-git commit\"")
commit, err := w.Commit("delete go-git commit", &git.CommitOptions{
Author: &object.Signature{
Name: "pass-sys",
Email: "pass-sys",
When: time.Now(),
},
})
if err != nil {
return err
}
// Prints the current HEAD to verify that all worked well.
Info("git show -s")
_, err = r.CommitObject(commit)
if err != nil {
return err
}
return nil
}
/**
* @author xiaolong.li
* @time 2018-09-10
* @desc push 到git
*/
func GitPush () (error) {
rootPath := beego.AppConfig.String("jksfile.dir")
r, err := git.PlainOpen(rootPath)
if err != nil {
return err
}
Info("git push")
//ssh agent
//currentUser, err := user.Current()
//sshAuth, err := ssh.NewPublicKeysFromFile("git", currentUser.HomeDir+"/.ssh/id_rsa", "")
sshAuth := &githttp.BasicAuth{Username: beego.AppConfig.String("gitlab.user"), Password: beego.AppConfig.String("gitlab.password")}
// push using default options
err = r.Push(&git.PushOptions{
Auth: sshAuth,
})
if err != nil {
errorMsg := err.Error()
if strings.Contains(errorMsg, "non-fast-forward") {
w, err := r.Worktree()
if err != nil {
fmt.Printf("git.Worktree.err=" + err.Error())
return err
}
err = w.Pull(&git.PullOptions{
RemoteName: "origin",
RecurseSubmodules: git.DefaultSubmoduleRecursionDepth,
Auth: sshAuth,
})
if err != nil {
fmt.Printf("git.pull.err=" + err.Error())
return err
}
//再次push
err = r.Push(&git.PushOptions{
Auth: sshAuth,
})
if err != nil {
return err
}
return nil
}
return err
}
return nil
}
添加文件以及目录是调用WorkTree中的Add() 方法;首先看下Add 方法在哪个文件中,找到WorkTree.go中没有;为了快速找到Add 只能使用LiteIDE (go 开发的ide),可以直接连接到方法所在的文件worktree_status.go。
然后其中有remove方法:
func (w *Worktree) Add(path string) (plumbing.Hash, error) {
// TODO(mcuadros): remove plumbing.Hash from signature at v5.
s, err := w.Status()
if err != nil {
return plumbing.ZeroHash, err
}
idx, err := w.r.Storer.Index()
if err != nil {
return plumbing.ZeroHash, err
}
var h plumbing.Hash
var added bool
fi, err := w.Filesystem.Lstat(path)
if err != nil || !fi.IsDir() {
added, h, err = w.doAddFile(idx, s, path)
} else {
added, err = w.doAddDirectory(idx, s, path)
}
if err != nil {
return h, err
}
if !added {
return h, nil
}
return h, w.r.Storer.SetIndex(idx)
}
func (w *Worktree) doAddDirectory(idx *index.Index,
s Status, directory string) (added bool, err error) {
files, err := w.Filesystem.ReadDir(directory)
if err != nil {
return false, err
}
for _, file := range files {
name := path.Join(directory, file.Name())
var a bool
if file.IsDir() {
if file.Name() == GitDirName {
// ignore special git directory
continue
}
a, err = w.doAddDirectory(idx, s, name)
} else {
a, _, err = w.doAddFile(idx, s, name)
}
if err != nil {
return
}
if !added && a {
added = true
}
}
return
}
// AddGlob adds all paths, matching pattern, to the index. If pattern matches a
// directory path, all directory contents are added to the index recursively. No
// error is returned if all matching paths are already staged in index.
func (w *Worktree) AddGlob(pattern string) error {
files, err := util.Glob(w.Filesystem, pattern)
if err != nil {
return err
}
if len(files) == 0 {
return ErrGlobNoMatches
}
s, err := w.Status()
if err != nil {
return err
}
idx, err := w.r.Storer.Index()
if err != nil {
return err
}
var saveIndex bool
for _, file := range files {
fi, err := w.Filesystem.Lstat(file)
if err != nil {
return err
}
var added bool
if fi.IsDir() {
added, err = w.doAddDirectory(idx, s, file)
} else {
added, _, err = w.doAddFile(idx, s, file)
}
if err != nil {
return err
}
if !saveIndex && added {
saveIndex = true
}
}
if saveIndex {
return w.r.Storer.SetIndex(idx)
}
return nil
}
// doAddFile create a new blob from path and update the index, added is true if
// the file added is different from the index.
func (w *Worktree) doAddFile(idx *index.Index,
s Status, path string) (added bool, h plumbing.Hash, err error) {
if s.File(path).Worktree == Unmodified {
return false, h, nil
}
h, err = w.copyFileToStorage(path)
if err != nil {
if os.IsNotExist(err) {
added = true
h, err = w.deleteFromIndex(idx, path)
}
return
}
if err := w.addOrUpdateFileToIndex(idx, path, h); err != nil {
return false, h, err
}
return true, h, err
}
func (w *Worktree) copyFileToStorage(path string)
(hash plumbing.Hash, err error) {
fi, err := w.Filesystem.Lstat(path)
if err != nil {
return plumbing.ZeroHash, err
}
obj := w.r.Storer.NewEncodedObject()
obj.SetType(plumbing.BlobObject)
obj.SetSize(fi.Size())
writer, err := obj.Writer()
if err != nil {
return plumbing.ZeroHash, err
}
defer ioutil.CheckClose(writer, &err)
if fi.Mode()&os.ModeSymlink != 0 {
err = w.fillEncodedObjectFromSymlink(writer, path, fi)
} else {
err = w.fillEncodedObjectFromFile(writer, path, fi)
}
if err != nil {
return plumbing.ZeroHash, err
}
return w.r.Storer.SetEncodedObject(obj)
}
func (w *Worktree) fillEncodedObjectFromFile(dst io.Writer,
path string, fi os.FileInfo) (err error) {
src, err := w.Filesystem.Open(path)
if err != nil {
return err
}
defer ioutil.CheckClose(src, &err)
if _, err := io.Copy(dst, src); err != nil {
return err
}
return err
}
func (w *Worktree) fillEncodedObjectFromSymlink(dst io.Writer, path string,
fi os.FileInfo) error {
target, err := w.Filesystem.Readlink(path)
if err != nil {
return err
}
_, err = dst.Write([]byte(target))
return err
}
func (w *Worktree) addOrUpdateFileToIndex(idx *index.Index, filename string,
h plumbing.Hash) error {
e, err := idx.Entry(filename)
if err != nil && err != index.ErrEntryNotFound {
return err
}
if err == index.ErrEntryNotFound {
return w.doAddFileToIndex(idx, filename, h)
}
return w.doUpdateFileToIndex(e, filename, h)
}
func (w *Worktree) doAddFileToIndex(idx *index.Index,
filename string, h plumbing.Hash) error {
return w.doUpdateFileToIndex(idx.Add(filename), filename, h)
}
func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string,
h plumbing.Hash) error {
info, err := w.Filesystem.Lstat(filename)
if err != nil {
return err
}
e.Hash = h
e.ModifiedAt = info.ModTime()
e.Mode, err = filemode.NewFromOSFileMode(info.Mode())
if err != nil {
return err
}
if e.Mode.IsRegular() {
e.Size = uint32(info.Size())
}
fillSystemInfo(e, info.Sys())
return nil
}
// Remove removes files from the working tree and from the index.
func (w *Worktree) Remove(path string) (plumbing.Hash, error) {
// TODO(mcuadros): remove plumbing.Hash from signature at v5.
idx, err := w.r.Storer.Index()
if err != nil {
return plumbing.ZeroHash, err
}
var h plumbing.Hash
fi, err := w.Filesystem.Lstat(path)
if err != nil || !fi.IsDir() {
h, err = w.doRemoveFile(idx, path)
} else {
_, err = w.doRemoveDirectory(idx, path)
}
if err != nil {
return h, err
}
return h, w.r.Storer.SetIndex(idx)
}
func (w *Worktree) doRemoveDirectory(idx *index.Index,
directory string) (removed bool, err error) {
files, err := w.Filesystem.ReadDir(directory)
if err != nil {
return false, err
}
for _, file := range files {
name := path.Join(directory, file.Name())
var r bool
if file.IsDir() {
r, err = w.doRemoveDirectory(idx, name)
} else {
_, err = w.doRemoveFile(idx, name)
if err == index.ErrEntryNotFound {
err = nil
}
}
if err != nil {
return
}
if !removed && r {
removed = true
}
}
err = w.removeEmptyDirectory(directory)
return
}
func (w *Worktree) removeEmptyDirectory(path string) error {
files, err := w.Filesystem.ReadDir(path)
if err != nil {
return err
}
if len(files) != 0 {
return nil
}
return w.Filesystem.Remove(path)
}
func (w *Worktree) doRemoveFile(idx *index.Index, path string)
(plumbing.Hash, error) {
hash, err := w.deleteFromIndex(idx, path)
if err != nil {
return plumbing.ZeroHash, err
}
return hash, w.deleteFromFilesystem(path)
}
func (w *Worktree) deleteFromIndex(idx *index.Index, path string)
(plumbing.Hash, error) {
e, err := idx.Remove(path)
if err != nil {
return plumbing.ZeroHash, err
}
return e.Hash, nil
}
func (w *Worktree) deleteFromFilesystem(path string) error {
err := w.Filesystem.Remove(path)
if os.IsNotExist(err) {
return nil
}
return err
}
// RemoveGlob removes all paths, matching pattern, from the index. If pattern
// matches a directory path, all directory contents are removed from the index
// recursively.
func (w *Worktree) RemoveGlob(pattern string) error {
idx, err := w.r.Storer.Index()
if err != nil {
return err
}
entries, err := idx.Glob(pattern)
if err != nil {
return err
}
for _, e := range entries {
file := filepath.FromSlash(e.Name)
if _, err := w.Filesystem.Lstat(file); err != nil
&& !os.IsNotExist(err) {
return err
}
if _, err := w.doRemoveFile(idx, file); err != nil {
return err
}
dir, _ := filepath.Split(file)
if err := w.removeEmptyDirectory(dir); err != nil {
return err
}
}
return w.r.Storer.SetIndex(idx)
}
调用remove 然后commit 即可!!