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

wip: support for fileMode: false #970

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 30 additions & 3 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"sort"
"strconv"
"strings"

format "gopkg.in/src-d/go-git.v4/plumbing/format/config"
)
Expand Down Expand Up @@ -43,6 +44,10 @@ type Config struct {
// CommentChar is the character indicating the start of a
// comment for commands like commit and tag
CommentChar string
// FileMode is normally set to true to tell git to respect and store
// the executable bit, but it may be set to false in certain cases where
// those aren't handled correctly, most notably on Windows.
FileMode bool
}

Pack struct {
Expand Down Expand Up @@ -115,6 +120,7 @@ const (
fetchKey = "fetch"
urlKey = "url"
bareKey = "bare"
fileModeKey = "filemode"
worktreeKey = "worktree"
commentCharKey = "commentChar"
windowKey = "window"
Expand Down Expand Up @@ -148,11 +154,31 @@ func (c *Config) Unmarshal(b []byte) error {
return c.unmarshalRemotes()
}

// Based off of git source code
// https://github.com/git/git/blob/2d3b1c576c85b7f5db1f418907af00ab88e0c303/config.c#L1042-L1057
func parseBool(opts format.Options, key string, def bool) bool {
v, exists := opts.GetValue(key)
if !exists {
return def
}
switch strings.ToLower(v) {
case "false", "no", "off":
return false
case "true", "yes", "on":
return true
}
i, err := strconv.Atoi(v)
if err != nil {
return def
}
return i != 0
}

func (c *Config) unmarshalCore() {
s := c.Raw.Section(coreSection)
if s.Options.Get(bareKey) == "true" {
c.Core.IsBare = true
}

c.Core.IsBare = parseBool(s.Options, bareKey, c.Core.IsBare)
c.Core.FileMode = parseBool(s.Options, fileModeKey, true)

c.Core.Worktree = s.Options.Get(worktreeKey)
c.Core.CommentChar = s.Options.Get(commentCharKey)
Expand Down Expand Up @@ -234,6 +260,7 @@ func (c *Config) Marshal() ([]byte, error) {
func (c *Config) marshalCore() {
s := c.Raw.Section(coreSection)
s.SetOption(bareKey, fmt.Sprintf("%t", c.Core.IsBare))
s.SetOption(fileModeKey, fmt.Sprintf("%t", c.Core.FileMode))

if c.Core.Worktree != "" {
s.SetOption(worktreeKey, c.Core.Worktree)
Expand Down
10 changes: 8 additions & 2 deletions plumbing/format/config/option.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,13 +45,19 @@ func (opts Options) GoString() string {
// In order to get all possible values for the same key,
// use GetAll.
func (opts Options) Get(key string) string {
ret, _ := opts.GetValue(key)
return ret
}

// GetValue is similar to Get, but returns also whether the value was found.
func (opts Options) GetValue(key string) (string, bool) {
for i := len(opts) - 1; i >= 0; i-- {
o := opts[i]
if o.IsKey(key) {
return o.Value
return o.Value, true
}
}
return ""
return "", false
}

// GetAll returns all possible values for the same key.
Expand Down
21 changes: 20 additions & 1 deletion worktree_status.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,11 @@ func (w *Worktree) status(commit plumbing.Hash) (Status, error) {
return nil, err
}

cfg, err := w.r.Config()
if err != nil {
return nil, err
}

for _, ch := range right {
a, err := ch.Action()
if err != nil {
Expand Down Expand Up @@ -479,12 +484,26 @@ func (w *Worktree) doUpdateFileToIndex(e *index.Entry, filename string, h plumbi
return err
}

isNew := e.Hash == plumbing.ZeroHash
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can simply do e.Hash.IsZero()

e.Hash = h
e.ModifiedAt = info.ModTime()
e.Mode, err = filemode.NewFromOSFileMode(info.Mode())

cfg, err := w.r.Config()
if err != nil {
return err
}
if cfg.Core.FileMode || !info.Mode().IsRegular() {
e.Mode, err = filemode.NewFromOSFileMode(info.Mode())
if err != nil {
return err
}
} else if isNew {
// https://github.com/git/git/blob/2d3b1c576c85b7f5db1f418907af00ab88e0c303/cache.h#L276-L280
// If this is a new file, make it a regular file. Otherwise, e.Mode
// can be kept as-is. This avoids the index marking the file as modified
// when only the mode has changed and fileMode == false
e.Mode = filemode.Regular
}

if e.Mode.IsRegular() {
e.Size = uint32(info.Size())
Expand Down