Commit d87ddc63 authored by Dmitry Smirnov's avatar Dmitry Smirnov

Update upstream source from tag 'upstream/1.3.0+dfsg'

Update to upstream version '1.3.0+dfsg'
with Debian dir edf15275f444e0640930cbd76d390b2e1233917d
parents 16298f99 c8fd93ff
......@@ -2,5 +2,3 @@
/bin
/releases
/vendor/go1.*
.pc
......@@ -173,7 +173,7 @@ at the command line to view the contents of the object. (Use `--names=none` if y
By default, only statistics above a minimal level of concern are reported. Use `--verbose` (as above) to request that all statistics be output. Use `--threshold=<value>` to suppress the reporting of statistics below a specified level of concern. (`<value>` is interpreted as a numerical value corresponding to the number of asterisks.) Use `--critical` to report only statistics with a critical level of concern (equivalent to `--threshold=30`).
If you'd like the output in machine-readable format, including exact numbers, use the `--json` option.
If you'd like the output in machine-readable format, including exact numbers, use the `--json` option. You can use `--json-version=1` or `--json-version=2` to choose between old and new style JSON output.
To get a list of other options, run
......
......@@ -14,8 +14,8 @@ func NewCount32(n uint64) Count32 {
return Count32(n)
}
func (n Count32) ToUint64() uint64 {
return uint64(n)
func (n Count32) ToUint64() (uint64, bool) {
return uint64(n), n == math.MaxUint32
}
// Return the sum of two Count32s, capped at math.MaxUint32.
......@@ -62,8 +62,8 @@ func NewCount64(n uint64) Count64 {
return Count64(n)
}
func (n Count64) ToUint64() uint64 {
return uint64(n)
func (n Count64) ToUint64() (uint64, bool) {
return uint64(n), n == math.MaxUint64
}
// Return the sum of two Count64s, capped at math.MaxUint64.
......
......@@ -11,25 +11,43 @@ import (
func TestCount32(t *testing.T) {
assert := assert.New(t)
var value uint64
var overflow bool
c := counts.NewCount32(0)
assert.Equalf(uint64(0), c.ToUint64(), "NewCount32(0).ToUint64() should be 0")
value, overflow = c.ToUint64()
assert.Equalf(uint64(0), value, "NewCount32(0).ToUint64() should be 0")
assert.False(overflow, "NewCount32(0).ToUint64() does not overflow")
c.Increment(counts.Count32(0xf0000000))
assert.Equalf(uint64(0xf0000000), c.ToUint64(), "Count32(0xf0000000).ToUint64() value")
value, overflow = c.ToUint64()
assert.Equalf(uint64(0xf0000000), value, "Count32(0xf0000000).ToUint64() value")
assert.False(overflow, "NewCount32(0xf0000000).ToUint64() does not overflow")
c.Increment(counts.Count32(0xf0000000))
assert.Equalf(uint64(0xffffffff), c.ToUint64(), "Count32(0xffffffff).ToUint64() value")
value, overflow = c.ToUint64()
assert.Equalf(uint64(0xffffffff), value, "Count32(0xffffffff).ToUint64() value")
assert.True(overflow, "NewCount32(0xffffffff).ToUint64() overflows")
}
func TestCount64(t *testing.T) {
assert := assert.New(t)
var value uint64
var overflow bool
c := counts.NewCount64(0)
assert.Equalf(uint64(0), c.ToUint64(), "NewCount64(0).ToUint64() should be 0")
value, overflow = c.ToUint64()
assert.Equalf(uint64(0), value, "NewCount64(0).ToUint64() should be 0")
assert.False(overflow, "NewCount64(0).ToUint64() does not overflow")
c.Increment(counts.Count64(0xf000000000000000))
assert.Equalf(uint64(0xf000000000000000), c.ToUint64(), "Count64(0xf000000000000000).ToUint64() value")
value, overflow = c.ToUint64()
assert.Equalf(uint64(0xf000000000000000), value, "Count64(0xf000000000000000).ToUint64() value")
assert.False(overflow, "NewCount64(0xf000000000000000).ToUint64() does not overflow")
c.Increment(counts.Count64(0xf000000000000000))
assert.Equalf(uint64(0xffffffffffffffff), c.ToUint64(), "Count64(0xffffffffffffffff).ToUint64() value")
value, overflow = c.ToUint64()
assert.Equalf(uint64(0xffffffffffffffff), value, "Count64(0xffffffffffffffff).ToUint64() value")
assert.True(overflow, "NewCount64(0xffffffffffffffff).ToUint64() overflows")
}
......@@ -2,51 +2,61 @@ package counts
import (
"fmt"
"math"
)
type Prefix struct {
Name string
Multiplier uint64
// A quantity that can be made human-readable using Human().
type Humanable interface {
// Return the value as a uint64, and a boolean telling whether it
// overflowed.
ToUint64() (uint64, bool)
}
type Humaner interface {
Human([]Prefix, string) (string, string)
ToUint64() uint64
// An object that can format a Humanable in human-readable format.
type Humaner struct {
name string
prefixes []Prefix
}
var MetricPrefixes []Prefix
type Prefix struct {
Name string
Multiplier uint64
}
func init() {
MetricPrefixes = []Prefix{
var Metric = Humaner{
name: "metric",
prefixes: []Prefix{
{"", 1},
{"k", 1e3},
{"M", 1e6},
{"G", 1e9},
{"T", 1e12},
{"P", 1e15},
}
},
}
var BinaryPrefixes []Prefix
func init() {
BinaryPrefixes = []Prefix{
var Binary = Humaner{
name: "binary",
prefixes: []Prefix{
{"", 1 << (10 * 0)},
{"Ki", 1 << (10 * 1)},
{"Mi", 1 << (10 * 2)},
{"Gi", 1 << (10 * 3)},
{"Ti", 1 << (10 * 4)},
{"Pi", 1 << (10 * 5)},
}
},
}
// Format values, aligned, in `len(unit) + 10` or fewer characters
// (except for extremely large numbers).
func Human(n uint64, prefixes []Prefix, unit string) (string, string) {
prefix := prefixes[0]
func (h *Humaner) Name() string {
return h.name
}
// Format n, aligned, in `len(unit) + 10` or fewer characters (except
// for extremely large numbers).
func (h *Humaner) FormatNumber(n uint64, unit string) (string, string) {
prefix := h.prefixes[0]
wholePart := n
for _, p := range prefixes {
for _, p := range h.prefixes {
w := n / p.Multiplier
if w >= 1 {
wholePart = w
......@@ -72,18 +82,13 @@ func Human(n uint64, prefixes []Prefix, unit string) (string, string) {
}
}
func (n Count32) Human(prefixes []Prefix, unit string) (string, string) {
if n == math.MaxUint32 {
// Format values, aligned, in `len(unit) + 10` or fewer characters
// (except for extremely large numbers).
func (h *Humaner) Format(value Humanable, unit string) (string, string) {
n, overflow := value.ToUint64()
if overflow {
return "∞", unit
} else {
return Human(uint64(n), prefixes, unit)
}
}
func (n Count64) Human(prefixes []Prefix, unit string) (string, string) {
if n == math.MaxUint64 {
return "∞", unit
} else {
return Human(uint64(n), prefixes, unit)
}
return h.FormatNumber(n, unit)
}
......@@ -52,18 +52,18 @@ func TestMetric(t *testing.T) {
{12345678900000000000, "12346", "Pcd"}, // Not ideal, but ok
{0xffffffffffffffff, "18447", "Pcd"}, // Not ideal, but ok
} {
number, unit := counts.Human(ht.n, counts.MetricPrefixes, "cd")
number, unit := counts.Metric.FormatNumber(ht.n, "cd")
assert.Equalf(ht.number, number, "Number for %d in metric", ht.n)
assert.Equalf(ht.unit, unit, "Unit for %d in metric", ht.n)
if ht.n < 0xffffffff {
c := counts.NewCount32(ht.n)
number, unit := c.Human(counts.MetricPrefixes, "cd")
number, unit := counts.Metric.Format(c, "cd")
assert.Equalf(ht.number, number, "Number for Count32(%d) in metric", ht.n)
assert.Equalf(ht.unit, unit, "Unit for Count32(%d) in metric", ht.n)
}
if ht.n < 0xffffffffffffffff {
c := counts.NewCount64(ht.n)
number, unit := c.Human(counts.MetricPrefixes, "cd")
number, unit := counts.Metric.Format(c, "cd")
assert.Equalf(ht.number, number, "Number for Count64(%d) in metric", ht.n)
assert.Equalf(ht.unit, unit, "Unit for Count64(%d) in metric", ht.n)
}
......@@ -91,18 +91,18 @@ func TestBinary(t *testing.T) {
{1152921504606846976, "1024", "PiB"},
{0xffffffffffffffff, "16384", "PiB"},
} {
number, unit := counts.Human(ht.n, counts.BinaryPrefixes, "B")
number, unit := counts.Binary.FormatNumber(ht.n, "B")
assert.Equalf(ht.number, number, "Number for %d in binary", ht.n)
assert.Equalf(ht.unit, unit, "Unit for %d in binary", ht.n)
if ht.n < 0xffffffff {
c := counts.NewCount32(ht.n)
number, unit := c.Human(counts.BinaryPrefixes, "B")
number, unit := counts.Binary.Format(c, "B")
assert.Equalf(ht.number, number, "Number for Count32(%d) in binary", ht.n)
assert.Equalf(ht.unit, unit, "Unit for Count32(%d) in binary", ht.n)
}
if ht.n < 0xffffffffffffffff {
c := counts.NewCount64(ht.n)
number, unit := c.Human(counts.BinaryPrefixes, "B")
number, unit := counts.Binary.Format(c, "B")
assert.Equalf(ht.number, number, "Number for Count64(%d) in binary", ht.n)
assert.Equalf(ht.unit, unit, "Unit for Count64(%d) in binary", ht.n)
}
......@@ -113,16 +113,16 @@ func TestLimits32(t *testing.T) {
assert := assert.New(t)
c := counts.NewCount32(0xffffffff)
number, unit := c.Human(counts.MetricPrefixes, "cd")
assert.Equalf("∞", number, "Number for Count32(%d) in metric", c.ToUint64())
assert.Equalf("cd", unit, "Unit for Count32(%d) in metric", c.ToUint64())
number, unit := counts.Metric.Format(c, "cd")
assert.Equalf("∞", number, "Number for Count32(0xffffffff) in metric")
assert.Equalf("cd", unit, "Unit for Count32(0xffffffff) in metric")
}
func TestLimits64(t *testing.T) {
assert := assert.New(t)
c := counts.NewCount64(0xffffffffffffffff)
number, unit := c.Human(counts.MetricPrefixes, "B")
assert.Equalf("∞", number, "Number for Count64(%d) in metric", c.ToUint64())
assert.Equalf("B", unit, "Unit for Count64(%d) in metric", c.ToUint64())
number, unit := counts.Metric.Format(c, "B")
assert.Equalf("∞", number, "Number for Count64(0xffffffffffffffff) in metric")
assert.Equalf("B", unit, "Unit for Count64(0xffffffffffffffff) in metric")
}
......@@ -60,33 +60,36 @@ func mainImplementation() error {
var nameStyle sizes.NameStyle = sizes.NameStyleFull
var cpuprofile string
var jsonOutput bool
var jsonVersion uint
var threshold sizes.Threshold = 1
var progress bool
var version bool
pflag.BoolVar(&processBranches, "branches", false, "process all branches")
pflag.BoolVar(&processTags, "tags", false, "process all tags")
pflag.BoolVar(&processRemotes, "remotes", false, "process all remote-tracking branches")
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
pflag.VarP(
flags.BoolVar(&processBranches, "branches", false, "process all branches")
flags.BoolVar(&processTags, "tags", false, "process all tags")
flags.BoolVar(&processRemotes, "remotes", false, "process all remote-tracking branches")
flags.VarP(
sizes.NewThresholdFlagValue(&threshold, 0),
"verbose", "v", "report all statistics, whether concerning or not",
)
pflag.Lookup("verbose").NoOptDefVal = "true"
flags.Lookup("verbose").NoOptDefVal = "true"
pflag.Var(
flags.Var(
&threshold, "threshold",
"minimum level of concern (i.e., number of stars) that should be\n"+
" reported",
)
pflag.Var(
flags.Var(
sizes.NewThresholdFlagValue(&threshold, 30),
"critical", "only report critical statistics",
)
pflag.Lookup("critical").NoOptDefVal = "true"
flags.Lookup("critical").NoOptDefVal = "true"
pflag.Var(
flags.Var(
&nameStyle, "names",
"display names of large objects in the specified `style`:\n"+
" --names=none omit footnotes entirely\n"+
......@@ -94,23 +97,31 @@ func mainImplementation() error {
" --names=full show full names",
)
pflag.BoolVarP(&jsonOutput, "json", "j", false, "output results in JSON format")
flags.BoolVarP(&jsonOutput, "json", "j", false, "output results in JSON format")
flags.UintVar(&jsonVersion, "json-version", 1, "JSON format version to output (1 or 2)")
atty, err := isatty.Isatty(os.Stderr.Fd())
if err != nil {
atty = false
}
pflag.BoolVar(&progress, "progress", atty, "report progress to stderr")
pflag.BoolVar(&version, "version", false, "report the git-sizer version number")
pflag.Var(&NegatedBoolValue{&progress}, "no-progress", "suppress progress output")
pflag.Lookup("no-progress").NoOptDefVal = "true"
flags.BoolVar(&progress, "progress", atty, "report progress to stderr")
flags.BoolVar(&version, "version", false, "report the git-sizer version number")
flags.Var(&NegatedBoolValue{&progress}, "no-progress", "suppress progress output")
flags.Lookup("no-progress").NoOptDefVal = "true"
flags.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
flags.MarkHidden("cpuprofile")
pflag.StringVar(&cpuprofile, "cpuprofile", "", "write cpu profile to file")
pflag.CommandLine.MarkHidden("cpuprofile")
flags.SortFlags = false
pflag.CommandLine.SortFlags = false
err = flags.Parse(os.Args[1:])
if err != nil {
return err
}
pflag.Parse()
if jsonOutput && !(jsonVersion == 1 || jsonVersion == 2) {
return fmt.Errorf("JSON version must be 1 or 2")
}
if cpuprofile != "" {
f, err := os.Create(cpuprofile)
......@@ -130,7 +141,7 @@ func mainImplementation() error {
return nil
}
args := pflag.Args()
args := flags.Args()
if len(args) != 0 {
return errors.New("excess arguments")
......@@ -167,11 +178,20 @@ func mainImplementation() error {
}
if jsonOutput {
s, err := json.MarshalIndent(historySize, "", " ")
var j []byte
var err error
switch jsonVersion {
case 1:
j, err = json.MarshalIndent(historySize, "", " ")
case 2:
j, err = historySize.JSON(threshold, nameStyle)
default:
return fmt.Errorf("JSON version must be 1 or 2")
}
if err != nil {
return fmt.Errorf("could not convert %v to json: %s", historySize, err)
}
fmt.Printf("%s\n", s)
fmt.Printf("%s\n", j)
} else {
io.WriteString(os.Stdout, historySize.TableString(threshold, nameStyle))
}
......
......@@ -120,8 +120,15 @@ func NewRepository(path string) (*Repository, error) {
}
func (repo *Repository) gitCommand(callerArgs ...string) *exec.Cmd {
// Disable replace references when running our commands:
args := []string{"--no-replace-objects"}
args := []string{
// Disable replace references when running our commands:
"--no-replace-objects",
// Disable the warning that grafts are deprecated, since we
// want to set the grafts file to `/dev/null` below (to
// disable grafts even where they are supported):
"-c", "advice.graftFileDeprecated=false",
}
args = append(args, callerArgs...)
......@@ -303,17 +310,11 @@ func PrefixFilter(prefix string) ReferenceFilter {
}
var (
BranchesFilter ReferenceFilter
TagsFilter ReferenceFilter
RemotesFilter ReferenceFilter
BranchesFilter ReferenceFilter = PrefixFilter("refs/heads/")
TagsFilter ReferenceFilter = PrefixFilter("refs/tags/")
RemotesFilter ReferenceFilter = PrefixFilter("refs/remotes/")
)
func init() {
BranchesFilter = PrefixFilter("refs/heads/")
TagsFilter = PrefixFilter("refs/tags/")
RemotesFilter = PrefixFilter("refs/remotes/")
}
func notNilFilters(filters ...ReferenceFilter) []ReferenceFilter {
var ret []ReferenceFilter
for _, filter := range filters {
......@@ -569,13 +570,24 @@ type ObjectHeaderIter struct {
data string
}
// Iterate over an object header. `data` should be the object's
// contents, including the "\n\n" that separates the header from the
// rest of the contents. `name` is used in error messages.
// Iterate over a commit or tag object header. `data` should be the
// object's contents, which is usually terminated by a blank line that
// separates the header from the comment. However, annotated tags
// don't always include comments, and Git even tolerates commits
// without comments, so don't insist on a blank line. `name` is used
// in error messages.
func NewObjectHeaderIter(name string, data []byte) (ObjectHeaderIter, error) {
headerEnd := bytes.Index(data, []byte("\n\n"))
if headerEnd == -1 {
return ObjectHeaderIter{}, fmt.Errorf("%s has no header separator", name)
if len(data) == 0 {
return ObjectHeaderIter{}, fmt.Errorf("%s has zero length", name)
}
if data[len(data)-1] != '\n' {
return ObjectHeaderIter{}, fmt.Errorf("%s has no terminating LF", name)
}
return ObjectHeaderIter{name, string(data)}, nil
}
return ObjectHeaderIter{name, string(data[:headerEnd+1])}, nil
}
......
package sizes
import (
"bytes"
"fmt"
)
type Footnotes struct {
footnotes []string
indexes map[string]int
}
func NewFootnotes() *Footnotes {
return &Footnotes{
indexes: make(map[string]int),
}
}
func (f *Footnotes) CreateCitation(footnote string) string {
if footnote == "" {
return ""
}
index, ok := f.indexes[footnote]
if !ok {
index = len(f.indexes) + 1
f.footnotes = append(f.footnotes, footnote)
f.indexes[footnote] = index
}
return fmt.Sprintf("[%d]", index)
}
func (f *Footnotes) String() string {
if len(f.footnotes) == 0 {
return ""
}
buf := &bytes.Buffer{}
buf.WriteByte('\n')
for i, footnote := range f.footnotes {
index := i + 1
citation := fmt.Sprintf("[%d]", index)
fmt.Fprintf(buf, "%-4s %s\n", citation, footnote)
}
return buf.String()
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment