Codebase list dh-make-golang / upstream/0.0_git20180305.d24646f progress.go
upstream/0.0_git20180305.d24646f

Tree @upstream/0.0_git20180305.d24646f (Download .tar.gz)

progress.go @upstream/0.0_git20180305.d24646fraw · history · blame

package main

import (
	"fmt"
	"os"
	"path/filepath"
	"strings"
	"time"
)

// #include <unistd.h>
// #include <stdbool.h>
//
// bool stdoutisatty() {
//   return isatty(STDOUT_FILENO);
// }
import "C"

const (
	_ = 1 << (10 * iota)
	Kibi
	Mebi
	Gibi
	Tebi
	Pebi
	Exbi
)

func humanizeBytes(b int64) string {
	if b > Tebi {
		return fmt.Sprintf("%.2f TiB", float64(b)/float64(Tebi))
	} else if b > Gibi {
		return fmt.Sprintf("%.2f GiB", float64(b)/float64(Gibi))
	} else if b > Mebi {
		return fmt.Sprintf("%.2f MiB", float64(b)/float64(Mebi))
	} else {
		return fmt.Sprintf("%.2f KiB", float64(b)/float64(Kibi))
	}
}

func progressSize(prefix, path string, done chan struct{}) {
	// previous holds how many bytes the previous line contained, so that we
	// can clear it in its entirety.
	var previous int
	tty := C.stdoutisatty()
	for {
		if tty {
			var usage int64
			filepath.Walk(path, func(path string, info os.FileInfo, err error) error {
				if err == nil && info.Mode().IsRegular() {
					usage += info.Size()
				}
				return nil
			})
			fmt.Printf("\r%s", strings.Repeat(" ", previous))
			previous, _ = fmt.Printf("\r%s: %s", prefix, humanizeBytes(usage))
		}

		select {
		case <-done:
			fmt.Printf("\r")
			return
		case <-time.After(250 * time.Millisecond):
			break
		}
	}
}