Skip to content

Commit

Permalink
bug fixes + progress refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
odeke-em committed Apr 14, 2015
1 parent cf4517f commit e8e7a02
Show file tree
Hide file tree
Showing 8 changed files with 221 additions and 77 deletions.
62 changes: 41 additions & 21 deletions src/changes.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,13 @@ import (
"github.com/odeke-em/log"
)

type destination int

const (
SelectSrc = 1 << iota
SelectDest
)

type dirList struct {
remote *File
local *File
Expand Down Expand Up @@ -293,20 +300,19 @@ func merge(remotes, locals chan *File) (merged []*dirList) {
return
}

func reduceToSize(changes []*Change, fromSrc bool) (totalSize int64) {
totalSize = 0
func reduceToSize(changes []*Change, destMask destination) (srcSize, destSize int64) {
fromSrc := (destMask & SelectSrc) != 0
fromDest := (destMask & SelectDest) != 0

for _, c := range changes {
if fromSrc {
if c.Src != nil {
totalSize += c.Src.Size
}
} else {
if c.Dest != nil {
totalSize += c.Dest.Size
}
if fromSrc && c.Src != nil {
srcSize += c.Src.Size
}
if fromDest && c.Dest != nil {
destSize += c.Dest.Size
}
}
return totalSize
return
}

func conflict(src, dest *File, index *config.Index, push bool) bool {
Expand Down Expand Up @@ -379,13 +385,13 @@ func warnConflictsPersist(logy *log.Logger, conflicts []*Change) {
}
}

func printChanges(logy *log.Logger, changes []*Change, reduce bool) {
opMap := map[int]sizeCounter{}
func opChangeCount(changes []*Change) map[Operation]sizeCounter {
opMap := map[Operation]sizeCounter{}

for _, c := range changes {
op := c.Op()
if op != OpNone {
logy.Logln(c.Symbol(), c.Path)
if op == OpNone {
continue
}
counter := opMap[op]
counter.count += 1
Expand All @@ -398,25 +404,39 @@ func printChanges(logy *log.Logger, changes []*Change, reduce bool) {
opMap[op] = counter
}

return opMap
}

func previewChanges(logy *log.Logger, cl []*Change, reduce bool, opMap map[Operation]sizeCounter) {
for _, c := range cl {
op := c.Op()
if op != OpNone {
logy.Logln(c.Symbol(), c.Path)
}
}

if reduce {
for op, counter := range opMap {
if counter.count < 1 {
continue
}
_, name := opToString(op)
_, name := op.description()
logy.Logf("%s %s\n", name, counter.String())
}
}
}

func printChangeList(logy *log.Logger, changes []*Change, noPrompt bool, noClobber bool) bool {
func printChangeList(logy *log.Logger, changes []*Change, noPrompt bool, noClobber bool) (bool, *map[Operation]sizeCounter) {
if len(changes) == 0 {
logy.Logln("Everything is up-to-date.")
return false
return false, nil
}
if noPrompt {
return true
return true, nil
}
printChanges(logy, changes, true)
return promptForChanges()

opMap := opChangeCount(changes)
previewChanges(logy, changes, true, opMap)

return promptForChanges(), &opMap
}
17 changes: 12 additions & 5 deletions src/diff.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func (g *Commands) Diff() (err error) {
if dErr != nil {
g.log.LogErrln(dErr)
}
g.log.Logf("\n%s\n", Ruler)
}
return
}
Expand Down Expand Up @@ -96,20 +95,28 @@ func (g *Commands) perDiff(change *Change, diffProgPath, cwd string) (err error)
change.Path, l.Size)
}

mask := fileDifferences(r, l, g.opts.IgnoreChecksum)
if mask == DifferNone {
// No output when "no changes found"
return nil
}

typeName := "File"
if l.IsDir {
typeName = "Directory"
}
g.log.Logf("%s: %s\n", typeName, change.Path)
mask := fileDifferences(r, l, g.opts.IgnoreChecksum)

if modTimeDiffers(mask) {
g.log.Logf("* %-15s %-40s\n* %-15s %-40s\n",
"local:", toUTCString(l.ModTime), "remote:", toUTCString(r.ModTime))
} else if mask == DifferNone {
// No output when "no changes found"
return nil

if mask == DifferModTime { // No further change
return
}
}

defer g.log.Logf("\n%s\n", Ruler)
var frTmp, fl *os.File
var blob io.ReadCloser

Expand Down
23 changes: 23 additions & 0 deletions src/misc.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,29 @@ func readCommentedFile(p, comment string) (clauses []string, err error) {
return
}

func chunkInt64(v int64) chan int {
var maxInt int
maxInt = 1<<31 - 1
maxIntCast := int64(maxInt)

chunks := make(chan int)

go func() {
q, r := v/maxIntCast, v%maxIntCast
for i := int64(0); i < q; i += 1 {
chunks <- maxInt
}

if r > 0 {
chunks <- int(r)
}

close(chunks)
}()

return chunks
}

func NonEmptyStrings(v []string) (splits []string) {
for _, elem := range v {
if elem != "" {
Expand Down
60 changes: 48 additions & 12 deletions src/pull.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,12 @@ func (g *Commands) Pull() (err error) {

nonConflicts := *nonConflictsPtr

ok := printChangeList(g.log, nonConflicts, !g.opts.canPrompt(), g.opts.NoClobber)
ok, opMap := printChangeList(g.log, nonConflicts, !g.opts.canPrompt(), g.opts.NoClobber)
if !ok {
return
}

return g.playPullChangeList(nonConflicts, g.opts.Exports)
return g.playPullChanges(nonConflicts, g.opts.Exports, opMap)
}

func (g *Commands) PullMatches() (err error) {
Expand Down Expand Up @@ -117,11 +117,12 @@ func (g *Commands) PullMatches() (err error) {

nonConflicts := *nonConflictsPtr

ok := printChangeList(g.log, nonConflicts, !g.opts.canPrompt(), g.opts.NoClobber)
if ok {
return g.playPullChangeList(nonConflicts, g.opts.Exports)
ok, opMap := printChangeList(g.log, nonConflicts, !g.opts.canPrompt(), g.opts.NoClobber)
if !ok {
return nil
}
return nil

return g.playPullChanges(nonConflicts, g.opts.Exports, opMap)
}

func (g *Commands) PullPiped() (err error) {
Expand Down Expand Up @@ -152,12 +153,24 @@ func (g *Commands) PullPiped() (err error) {
return
}

func (g *Commands) playPullChangeList(cl []*Change, exports []string) (err error) {
func (g *Commands) playPullChanges(cl []*Change, exports []string, opMap *map[Operation]sizeCounter) (err error) {
var next []*Change

pullSize := reduceToSize(cl, true)
if opMap == nil {
result := opChangeCount(cl)
opMap = &result
}

totalSize := int64(0)
ops := *opMap

for _, counter := range ops {
totalSize += counter.src
}

g.taskStart(int64(len(cl)) + pullSize)
g.taskStart(int64(len(cl)) + totalSize)

defer close(g.rem.progressChan)

// TODO: Only provide precedence ordering if all the other options are allowed
// Currently noop on sorting by precedence
Expand Down Expand Up @@ -221,6 +234,8 @@ func (g *Commands) localMod(wg *sync.WaitGroup, change *Change, exports []string

destAbsPath := g.context.AbsPathOf(change.Path)

downloadPerformed := false

// Simple heuristic to avoid downloading all the
// content yet it could just be a modTime difference
mask := fileDifferences(change.Src, change.Dest, change.IgnoreChecksum)
Expand All @@ -229,8 +244,19 @@ func (g *Commands) localMod(wg *sync.WaitGroup, change *Change, exports []string
if err = g.download(change, exports); err != nil {
return
}
downloadPerformed = true
}
err = os.Chtimes(destAbsPath, change.Src.ModTime, change.Src.ModTime)

// Update progress for the case in which you are only Chtime-ing
// since progress for downloaded files is already handled separately
if !downloadPerformed {
chunks := chunkInt64(change.Src.Size)
for n := range chunks {
g.rem.progressChan <- n
}
}

return
}

Expand Down Expand Up @@ -276,9 +302,19 @@ func (g *Commands) localAdd(wg *sync.WaitGroup, change *Change, exports []string
}

func (g *Commands) localDelete(wg *sync.WaitGroup, change *Change) (err error) {
defer g.taskDone()
defer wg.Done()
return os.RemoveAll(change.Dest.BlobAt)
defer func() {
if err == nil {
chunks := chunkInt64(change.Dest.Size)
for n := range chunks {
g.rem.progressChan <- n
}
}

g.taskDone()
wg.Done()
}()
err = os.RemoveAll(change.Dest.BlobAt)
return
}

func touchFile(path string) (err error) {
Expand Down
Loading

0 comments on commit e8e7a02

Please sign in to comment.