Skip to content
This repository was archived by the owner on Sep 11, 2020. It is now read-only.
This repository was archived by the owner on Sep 11, 2020. It is now read-only.

plumbing.Reference.IsBranch is not working well on windows #462

@mpppk

Description

@mpppk

To Reproduce the problem

  1. Create some branches
> git branch
master
some_features
  1. Execute below code.
r, _ := git.PlainOpen(".")
refs, _ := r.References()
refs.ForEach(func(ref *plumbing.Reference) error {
	fmt.Println(ref.Name(), ref.IsBranch())
	return nil
})

Expected behavior

refs\heads\some_features true
refs\heads\master true
refs\remotes\origin\HEAD false
refs\remotes\origin\some_features false
refs\remotes\origin\master false
HEAD false

IsBranch() should return true if reference name is "master" or "some_features".

Actual behavior

refs/remotes/origin/master false
refs\heads\some_features false
refs\heads\master false
refs\remotes\origin\HEAD false
refs\remotes\origin\some_features false
refs\remotes\origin\master false
HEAD false

There are two problems.

  1. Path separators "/" and "\" are mixed
  2. refs\heads\master and refs\heads\some_features are branch but IsBranch() return false

Cause of problems

Cause of the path separators are mixed

If reference is retrieved from refs/heads, refs/remotes and refs/tags, path separator is determined by DotGit.fs.Join when read reference path.
So path separator will be "\" on windows.

dotgit.go 468

func (d *DotGit) readReferenceFile(refsPath, refFile string) (ref *plumbing.Reference, err error) {
	path := d.fs.Join(refsPath, refFile)

But if reference is retrieved from packed-refs, the path written in the file has "/" as path separator even if it on windows and the path is used as reference path direct.

packed-refs example:

# pack-refs with: peeled fully-peeled
65fdeb52c589aed517facc3b2b0edefe5d26518d refs/remotes/origin/master
^29c35f9a455bf5ed601ec47d3ca93da079ce428a

Cause why IsBranch() return false even if it is branch

Windows path separator will be "\" but IsBranch() expect "/"

func (r *Reference) IsBranch() bool {
	return strings.HasPrefix(string(r.n), refHeadPrefix)
}
const (
	refPrefix       = "refs/"
	refHeadPrefix   = refPrefix + "heads/"
	refTagPrefix    = refPrefix + "tags/"
	refRemotePrefix = refPrefix + "remotes/"
	refNotePrefix   = refPrefix + "notes/"
	symrefPrefix    = "ref: "
)

Possible Fix

I think there are two ways to fix these problems.

  1. Always join reference path by "/"
  2. Use strings.Join when concat RefsPrefixes and replace "/" to "\" when retrieve reference path from packed-refs if running on windows.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions