Comments (2)
Let me post my workaround of this bug in the client code
//go-git library has a bug in pull operation. When the directory contains unstaged files it stops the reset --merge operation on the half way,
//which caused inconsistency in the working directory of git. To be precise all changes which come from new commits from remote repo, will be staged in reverted state
func pullRecover(gitRepo *git.Repository, pre, post *plumbing.Reference, preStatus *git.Status) *misc.RuntimeError {
gwt, err := gitRepo.Worktree()
gitPath := gwt.Filesystem.Root()
if err != nil {
return misc.NewRuntimeError("cannot get git worktree", 190, err)
}
postStatus, err := gwt.Status()
if err != nil {
helpers.Debugf("cannot get post git status. Error: %s", err)
return misc.NewRuntimeError("cannot get post git status", 193, err)
} else {
helpers.Debugf("Git %s status after pull \n%s", gitPath, postStatus.String())
}
postCommitObject, err := gitRepo.CommitObject(post.Hash())
if err != nil {
helpers.Debugf("cannot get post commit object. Error: %s", err)
return misc.NewRuntimeError("cannot get post commit object", 194, err)
}
postComTree, err := postCommitObject.Tree()
if err != nil {
helpers.Debugf("cannot get post commit tree. Error: %s", err)
return misc.NewRuntimeError("cannot get post commit tree", 195, err)
}
preCommitObject, err := gitRepo.CommitObject(pre.Hash())
if err != nil {
helpers.Debugf("cannot get pre commit object. Error: %s", err)
return misc.NewRuntimeError("cannot get pre commit object", 196, err)
}
preComTree, err := preCommitObject.Tree()
if err != nil {
helpers.Debugf("cannot get pre commit tree. Error: %s", err)
return misc.NewRuntimeError("cannot get pre commit tree", 197, err)
}
changes, err := preComTree.Diff(postComTree)
if err != nil {
helpers.Debugf("failed to compute git diff. Error %s", err)
return misc.NewRuntimeError("failed to compute git diff", 198, err)
}
successful := true
//Check statuses
for f, fs := range *preStatus {
if fs.Staging == git.Unmodified && fs.Worktree == git.Modified {
pfs := postStatus.File(f)
if pfs.Worktree != fs.Worktree {
helpers.Debugf("worktree status of the file %s has been changed after pull. Please merge manually", f)
return misc.NewRuntimeError(fmt.Sprintf("worktree status of the file %s has been changed after pull", f), 192, nil)
}
if pfs.Staging != fs.Staging {
helpers.Debugf("staging status of the file %s has been changed after pull. Please merge manually", f)
return misc.NewRuntimeError(fmt.Sprintf("staging status of the file %s has been changed after pull", f), 192, nil)
}
}
}
for _, c := range changes {
err = resetFile(gitRepo, c, post, false) //err = gwt.Checkout(&git.CheckoutOptions{Force: true, Hash: postHead.Hash()})
if err != nil {
helpers.Debugf("failed to reset file %s. Error %s", c.To.Name, err)
successful = false
}
}
if successful {
return nil
}
return misc.NewRuntimeError("failed to recover the pull. Please fix git %s repo manually", 199, nil)
}
//resets a particular file to the correct version
func resetFile(repo *git.Repository, c *object.Change, ref *plumbing.Reference, reverse bool) error {
var obj object.ChangeEntry
if reverse {
obj = c.From
} else {
obj = c.To
}
gwt, err := repo.Worktree()
if err != nil {
helpers.Debugf("cannot get git worktree. Error %s", err)
return err
}
source, err := obj.Tree.TreeEntryFile(&obj.TreeEntry)
if err != nil {
helpers.Debugf("cannot get modified file from tree. Error %s", err)
return err
}
//
fMode, err := obj.TreeEntry.Mode.ToOSFileMode()
if err != nil {
helpers.Debugf("cannot get a file mode. Error: %s", err)
return err
}
gitPath := gwt.Filesystem.Root()
absPath := path.Join(gitPath, obj.Name)
dest, err := gwt.Filesystem.OpenFile(obj.Name, os.O_CREATE|os.O_WRONLY, fMode)
//dest, err := os.OpenFile(destPath, os.O_CREATE|os.O_WRONLY, fMode)
if err != nil {
helpers.Debugf("canot open destination file")
return err
}
defer dest.Close()
sourceReader, err := source.Reader()
if err != nil {
helpers.Debugf("failed to get reader from source file")
return err
}
defer sourceReader.Close()
//buf := make([]bwrittenyte, 2048)
//_, err = io.CopyBuffer(dest, sourceReader, buf)
err = dest.Truncate(0)
if err != nil {
helpers.Debugf("failed to truncate file %s Error: %s", obj.Name, err)
return err
}
_, err = dest.Seek(0, 0)
if err != nil {
helpers.Debugf("failed to jump on the beginning of file %s Error: %s", obj.Name, err)
return err
}
written, err := io.Copy(dest, sourceReader)
if err != nil {
helpers.Debugf("failed to copy file. Written: %d Error: %s", written, err)
return err
} else {
helpers.Debugf("file %s has been restored to the %s state", obj.Name, ref.Name())
}
i, err := repo.Storer.Index()
if err != nil {
helpers.Debugf("cannot get i of repository. Error %s", err)
return err
}
entry, err := i.Entry(obj.Name)
if err != nil {
helpers.Debugf("cannot get entry %s Error %s", obj.Name, err)
return err
}
fi, err := os.Stat(absPath)
if err != nil {
helpers.Debugf("cannot stat %s file info. Error: %s", obj.Name, err)
return err
}
_, err = i.Remove(obj.Name)
if err != nil {
helpers.Debugf("cannot remove index %s Error: %s", obj.Name, err)
}
helpers.Debug("Entry " + entry.Name)
mode, err := filemode.NewFromOSFileMode(fMode)
if err != nil {
helpers.Debugf("cannot get file %s mode. Error %s", obj.Name, err)
}
e := index.Entry{
Hash: obj.TreeEntry.Hash,
Name: obj.Name,
Mode: mode,
ModifiedAt: fi.ModTime(),
Size: uint32(fi.Size()),
}
i.Entries = append(i.Entries, &e)
err = repo.Storer.SetIndex(i)
if err != nil {
helpers.Debugf("failed to set index. Error: %s", err)
}
return nil
}
from go-git.
To help us keep things tidy and focus on the active tasks, we've introduced a stale bot to spot issues/PRs that haven't had any activity in a while.
This particular issue hasn't had any updates or activity in the past 90 days, so it's been labeled as 'stale'. If it remains inactive for the next 30 days, it'll be automatically closed.
We understand everyone's busy, but if this issue is still important to you, please feel free to add a comment or make an update to keep it active.
Thanks for your understanding and cooperation!
from go-git.
Related Issues (20)
- Assignment mismatch in ls/main.go example
- `CommitObject` failed to find commit when objects are from `objects/info/alternates` HOT 1
- worktree.Add does not add a modified file correctly while git add works as expected
- It seems that AlternateFS doesn't work with git's `clone --shared`
- How to clone a particular tag of a GitHub repository ?
- ref.Name().Short() doesn't match format git format refs/remotes/origin/*
- Create a release with `github.com/cloudflare/[email protected]` HOT 3
- storage example update to use go-git v5 HOT 4
- Cannot handle empty ReferenceUpdateRequest
- How to include custom transport during clone ? HOT 1
- `gitattributes.ReadAttributesFile` does not close file
- $HOME is not defined HOT 2
- Amend Commit doesn't work HOT 1
- Empty File Renames/Deletions not returned by Patch.FilePatches()
- An error occurred when cloning a large repo.
- Add support for bundles HOT 2
- Unable to clone/push to an empty repo HOT 2
- Add option to skip git status check when adding a file HOT 3
- `CleanOptions.Dir` differs from `-d` flag in `git clean`
- How to list all the repositories belong to a user? HOT 3
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from go-git.