<commit_before>// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// Package checks implements pre-made checks for pcg.
//
// This package defines the `pre-commit-go.yml` configuration file format and
// implements all the checks.
package checks

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"os"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/maruel/pre-commit-go/internal"
	"github.com/maruel/pre-commit-go/scm"
)

// CheckPrerequisite describe a Go package that is needed to run a Check.
//
// It must list a command that is to be executed and the expected exit code to
// verify that the custom tool is properly installed. If the executable is not
// detected, "go get $URL" will be executed.
type CheckPrerequisite struct {
	// HelpCommand is the help command to run to detect if this prerequisite is
	// installed or not. This command should have no adverse effect and must be
	// fast to execute.
	HelpCommand []string `yaml:"help_command"`
	// ExpectedExitCode is the exit code expected when HelpCommand is executed.
	ExpectedExitCode int `yaml:"expected_exit_code"`
	// URL is the url to fetch as `go get URL`.
	URL string
}

// IsPresent returns true if the prerequisite is present on the system.
func (c *CheckPrerequisite) IsPresent() bool {
	_, exitCode, _ := internal.Capture(cwd, nil, c.HelpCommand...)
	return exitCode == c.ExpectedExitCode
}

// Check describes an check to be executed on the code base.
type Check interface {
	// GetDescription returns the check description.
	GetDescription() string
	// GetName returns the check name.
	GetName() string
	// GetPrerequisites lists all the go packages to be installed before running
	// this check.
	GetPrerequisites() []CheckPrerequisite
	// Run executes the check.
	Run(change scm.Change, options *Options) error
}

// Native checks.

// Build builds packages without tests via 'go build'.
type Build struct {
	BuildAll  bool     `yaml:"build_all"`
	ExtraArgs []string `yaml:"extra_args"`
}

// GetDescription implements Check.
func (b *Build) GetDescription() string {
	return "builds all packages"
}

// GetName implements Check.
func (b *Build) GetName() string {
	return "build"
}

// GetPrerequisites implements Check.
func (b *Build) GetPrerequisites() []CheckPrerequisite {
	return nil
}

// Lock implements sync.Locker.
func (b *Build) Lock() {
	buildLock.Lock()
}

// Unlock implements sync.Locker.
func (b *Build) Unlock() {
	buildLock.Unlock()
}

// Run implements Check.
func (b *Build) Run(change scm.Change, options *Options) error {
	// go build accepts packages, not files.
	// Cannot build concurrently since it leaves files in the tree.
	// TODO(maruel): Build in a temporary directory to not leave junk in the tree
	// with -o. On the other hand, ./... and -o foo are incompatible. But
	// building would have to be done in an efficient way by looking at which
	// package builds what, to not result in a O(n²) algorithm.
	pkgs := change.Indirect().Packages()
	if len(pkgs) == 0 {
		return nil
	}
	args := append([]string{"go", "build"}, b.ExtraArgs...)
	out, _, err := capture(change.Repo(), append(args, pkgs...)...)
	if len(out) != 0 {
		return fmt.Errorf("%s failed: %s", strings.Join(args, " "), out)
	}
	if err != nil {
		return fmt.Errorf("%s failed: %s", strings.Join(args, " "), err.Error())
	}
	return nil
}

// Copyright looks for copyright headers in all files.
type Copyright struct {
	Header string
}

// GetDescription implements Check.
func (c *Copyright) GetDescription() string {
	return "enforces all .go sources have copyright"
}

// GetName implements Check.
func (c *Copyright) GetName() string {
	return "copyright"
}

// GetPrerequisites implements Check.
func (c *Copyright) GetPrerequisites() []CheckPrerequisite {
	return nil
}

// Run implements Check.
func (c *Copyright) Run(change scm.Change, options *Options) error {
	var badFiles []string
	prefix := []byte(c.Header)
	// This this serially since it's I/O bound and will compete with process
	// startup of other checks.
	for _, f := range change.Changed().GoFiles() {
		if content := change.Content(f); content != nil {
			if !bytes.HasPrefix(content, prefix) {
				badFiles = append(badFiles, f)
			}
		} else {
			badFiles = append(badFiles, f)
		}
	}
	if len(badFiles) != 0 {
		return fmt.Errorf("files have invalid copyright header:\n  %s", strings.Join(badFiles, "\n  "))
	}
	return nil
}<commit_msg>Fix Copyright check for ignored files.<commit_after>// Copyright 2015 <NAME>. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.

// Package checks implements pre-made checks for pcg.
//
// This package defines the `pre-commit-go.yml` configuration file format and
// implements all the checks.
package checks

import (
	"bytes"
	"errors"
	"fmt"
	"log"
	"os"
	"sort"
	"strings"
	"sync"
	"time"

	"github.com/maruel/pre-commit-go/internal"
	"github.com/maruel/pre-commit-go/scm"
)

// CheckPrerequisite describe a Go package that is needed to run a Check.
//
// It must list a command that is to be executed and the expected exit code to
// verify that the custom tool is properly installed. If the executable is not
// detected, "go get $URL" will be executed.
type CheckPrerequisite struct {
	// HelpCommand is the help command to run to detect if this prerequisite is
	// installed or not. This command should have no adverse effect and must be
	// fast to execute.
	HelpCommand []string `yaml:"help_command"`
	// ExpectedExitCode is the exit code expected when HelpCommand is executed.
	ExpectedExitCode int `yaml:"expected_exit_code"`
	// URL is the url to fetch as `go get URL`.
	URL string
}

// IsPresent returns true if the prerequisite is present on the system.
func (c *CheckPrerequisite) IsPresent() bool {
	_, exitCode, _ := internal.Capture(cwd, nil, c.HelpCommand...)
	return exitCode == c.ExpectedExitCode
}

// Check describes an check to be executed on the code base.
type Check interface {
	// GetDescription returns the check description.
	GetDescription() string
	// GetName returns the check name.
	GetName() string
	// GetPrerequisites lists all the go packages to be installed before running
	// this check.
	GetPrerequisites() []CheckPrerequisite
	// Run executes the check.
	Run(change scm.Change, options *Options) error
}

// Native checks.

// Build builds packages without tests via 'go build'.
type Build struct {
	BuildAll  bool     `yaml:"build_all"`
	ExtraArgs []string `yaml:"extra_args"`
}

// GetDescription implements Check.
func (b *Build) GetDescription() string {
	return "builds all packages"
}

// GetName implements Check.
func (b *Build) GetName() string {
	return "build"
}

// GetPrerequisites implements Check.
func (b *Build) GetPrerequisites() []CheckPrerequisite {
	return nil
}

// Lock implements sync.Locker.
func (b *Build) Lock() {
	buildLock.Lock()
}

// Unlock implements sync.Locker.
func (b *Build) Unlock() {
	buildLock.Unlock()
}

// Run implements Check.
func (b *Build) Run(change scm.Change, options *Options) error {
	// go build accepts packages, not files.
	// Cannot build concurrently since it leaves files in the tree.
	// TODO(maruel): Build in a temporary directory to not leave junk in the tree
	// with -o. On the other hand, ./... and -o foo are incompatible. But
	// building would have to be done in an efficient way by looking at which
	// package builds what, to not result in a O(n²) algorithm.
	pkgs := change.Indirect().Packages()
	if len(pkgs) == 0 {
		return nil
	}
	args := append([]string{"go", "build"}, b.ExtraArgs...)
	out, _, err := capture(change.Repo(), append(args, pkgs...)...)
	if len(out) != 0 {
		return fmt.Errorf("%s failed: %s", strings.Join(args, " "), out)
	}
	if err != nil {
		return fmt.Errorf("%s failed: %s", strings.Join(args, " "), err.Error())
	}
	return nil
}

// Copyright looks for copyright headers in all files.
type Copyright struct {
	Header string
}

// GetDescription implements Check.
func (c *Copyright) GetDescription() string {
	return "enforces all .go sources have copyright"
}

// GetName implements Check.
func (c *Copyright) GetName() string {
	return "copyright"
}

// GetPrerequisites implements Check.
func (c *Copyright) GetPrerequisites() []CheckPrerequisite {
	return nil
}

// Run implements Check.
func (c *Copyright) Run(change scm.Change, options *Options) error {
	var badFiles []string
	prefix := []byte(c.Header)
	// This this serially since it's I/O bound and will compete with process
	// startup of other checks.
	for _, f := range change.Changed().GoFiles() {
		if !change.IsIgnored(f) {
			if content := change.Content(f); content != nil {
				if !bytes.HasPrefix(content, prefix) {
					badFiles = append(badFiles, f)
				}
			} else {
				badFiles = append(badFiles, f)
			}
		}
	}
	if len(badFiles) != 0 {
		return fmt.Errorf("files have invalid copyright header:\n  %s", strings.Join(badFiles, "\n  "))
	}
	return nil
}
{'fraction_non_alphanumeric': 0.11809544851966416, 'fraction_numerical': 0.001988510826336721, 'mean_word_length': 3.6354326676907323, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4391960', 'n_tokens_mistral': 2847, 'n_tokens_neox': 2730, 'n_words': 1083}