ronantakizawa/codereview-bench huggingface dataset:
Repository: go-gitea/gitea
File: modules/analyze/vendor.go (Go)

Code before:
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package analyze

import (
	"path/filepath"
	"regexp"

	"github.com/go-enry/go-enry/v2"
)

// vendorOverrideRe matches paths that go-enry marks as vendored but shouldn't
// be shown as "Vendored" in Gitea's diff view.
var vendorOverrideRe = regexp.MustCompile(`^\.(git(hub|ea)|forgejo)/`)

// IsVendor returns whether or not path is a vendor path.
// It uses go-enry's IsVendor function but overrides its detection for certain
// special cases that shouldn't be marked as vendored in the diff view.
// See https://github.com/go-gitea/gitea/issues/22618
func IsVendor(path string) bool {
	if !enry.IsVendor(path) {
		return false
	}

	// Override detection for these special cases.
	basename := filepath.Base(path)
	switch basename {
	case ".gitignore", ".gitattributes", ".gitmodules":
		return false
	}

	return !vendorOverrideRe.MatchString(path)
}


Review comment (suggestion):
```suggestion
// be shown as "Vendored" in diff view.
```

Code after:
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package analyze

import (
	"path"
	"strings"

	"github.com/go-enry/go-enry/v2"
)

// IsVendor returns whether the path is a vendor path.
// It uses go-enry's IsVendor function but overrides its detection for certain
// special cases that shouldn't be marked as vendored in the diff view.
func IsVendor(treePath string) bool {
	if !enry.IsVendor(treePath) {
		return false
	}

	// Override detection for single files
	basename := path.Base(treePath)
	switch basename {
	case ".gitignore", ".gitattributes", ".gitmodules":
		return false
	}
	if strings.HasPrefix(treePath, ".github/") || strings.HasPrefix(treePath, ".gitea/") {
		return false
	}
	return true
}
Repository: go-gitea/gitea
File: modules/analyze/vendor.go (Go)

Code before:
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package analyze

import (
	"path/filepath"
	"regexp"

	"github.com/go-enry/go-enry/v2"
)

// vendorOverrideRe matches paths that go-enry marks as vendored but shouldn't
// be shown as "Vendored" in diff view.
var vendorOverrideRe = regexp.MustCompile(`^\.(git(hub|ea)|forgejo)/`)

// IsVendor returns whether or not path is a vendor path.
// It uses go-enry's IsVendor function but overrides its detection for certain
// special cases that shouldn't be marked as vendored in the diff view.
// See https://github.com/go-gitea/gitea/issues/22618
func IsVendor(path string) bool {
	if !enry.IsVendor(path) {
		return false
	}

	// Override detection for these special cases.
	basename := filepath.Base(path)
	switch basename {
	case ".gitignore", ".gitattributes", ".gitmodules":
		return false
	}

	return !vendorOverrideRe.MatchString(path)
}


Review comment (suggestion):
```suggestion
	// Override detection for single files
```

Code after:
// Copyright 2021 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package analyze

import (
	"path"
	"strings"

	"github.com/go-enry/go-enry/v2"
)

// IsVendor returns whether the path is a vendor path.
// It uses go-enry's IsVendor function but overrides its detection for certain
// special cases that shouldn't be marked as vendored in the diff view.
func IsVendor(treePath string) bool {
	if !enry.IsVendor(treePath) {
		return false
	}

	// Override detection for single files
	basename := path.Base(treePath)
	switch basename {
	case ".gitignore", ".gitattributes", ".gitmodules":
		return false
	}
	if strings.HasPrefix(treePath, ".github/") || strings.HasPrefix(treePath, ".gitea/") {
		return false
	}
	return true
}
Repository: go-gitea/gitea
File: web_src/js/bootstrap.test.ts (TypeScript)

Code before:
import {shouldIgnoreError, showGlobalErrorMessage} from './bootstrap.ts';

test('showGlobalErrorMessage', () => {
  document.body.innerHTML = '<div class="page-content"></div>';
  showGlobalErrorMessage('test msg 1');
  showGlobalErrorMessage('test msg 2');
  showGlobalErrorMessage('test msg 1'); // duplicated

  expect(document.body.innerHTML).toContain('>test msg 1 (2)<');
  expect(document.body.innerHTML).toContain('>test msg 2<');
  expect(document.querySelectorAll('.js-global-error').length).toEqual(2);
});

test('shouldIgnoreError', () => {
  for (const url of [
    'https://gitea.test/assets/js/monaco.b359ef7e.js',
    'https://gitea.test/assets/js/monaco-editor.4a969118.worker.js',
    'https://gitea.test/assets/js/vendors-node_modules_pnpm_monaco-editor_0_55_1_node_modules_monaco-editor_esm_vs_base_common_-e11c7c.966a028d.js',
  ]) {
    const err = new Error('test');
    err.stack = `Error: test\n    at ${url}:1:1`;
    expect(shouldIgnoreError(err)).toEqual(true);
  }

  const otherError = new Error('test');
  otherError.stack = 'Error: test\n    at https://gitea.test/assets/js/index.js:1:1';

Review comment (suggestion):
```suggestion
import {showGlobalErrorMessage, shouldIgnoreError} from './bootstrap.ts';
```

Code after:
import {showGlobalErrorMessage, shouldIgnoreError} from './bootstrap.ts';

test('showGlobalErrorMessage', () => {
  document.body.innerHTML = '<div class="page-content"></div>';
  showGlobalErrorMessage('test msg 1');
  showGlobalErrorMessage('test msg 2');
  showGlobalErrorMessage('test msg 1'); // duplicated

  expect(document.body.innerHTML).toContain('>test msg 1 (2)<');
  expect(document.body.innerHTML).toContain('>test msg 2<');
  expect(document.querySelectorAll('.js-global-error').length).toEqual(2);
});

test('shouldIgnoreError', () => {
  for (const url of [
    'https://gitea.test/assets/js/monaco.b359ef7e.js',
    'https://gitea.test/assets/js/monaco-editor.4a969118.worker.js',
    'https://gitea.test/assets/js/vendors-node_modules_pnpm_monaco-editor_0_55_1_node_modules_monaco-editor_esm_vs_base_common_-e11c7c.966a028d.js',
  ]) {
    const err = new Error('test');
    err.stack = `Error: test\n    at ${url}:1:1`;
    expect(shouldIgnoreError(err)).toEqual(true);
  }

  const otherError = new Error('test');
  otherError.stack = 'Error: test\n    at https://gitea.test/assets/js/index.js:1:1';
Repository: go-gitea/gitea
File: web_src/js/features/codeeditor.ts (TypeScript)

Code before:
  const editorConfig = getEditorconfig(filenameInput);

  togglePreviewDisplay(isPreviewable);

  const {monaco, editor} = await createMonaco(textarea, filename, {
    ...getFileBasedOptions(filenameInput.value, lineWrapExts),
    ...getEditorConfigOptions(editorConfig),
  });

  filenameInput.addEventListener('input', onInputDebounce(() => {
    const filename = filenameInput.value;
    const previewable = previewableExts.has(extname(filename));
    togglePreviewDisplay(previewable);
    updateEditor(monaco, editor, filename, lineWrapExts);
  }));

  return editor;
}

function getEditorConfigOptions(ec: EditorConfig | null): MonacoOpts {
  if (!ec || !isObject(ec)) return {};

  const opts: MonacoOpts = {};
  opts.detectIndentation = !('indent_style' in ec) || !('indent_size' in ec);

  // we use indentSize='tabSize' so these numbers always match
  opts.tabSize = Number(ec.tab_width) || Number(ec.indent_size) || 4;

  if ('max_line_length' in ec) {
    opts.rulers = [Number(ec.max_line_length)];
  }

  opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true;
  opts.insertSpaces = ec.indent_style === 'space';
  opts.useTabStops = ec.indent_style === 'tab';
  return opts;
}


Review comment (suggestion):
```suggestion
  // with indentSize='tabSize', this also controls the `indentSize` option
```

Code after:
  const {monaco, editor} = await createMonaco(textarea, filename, {
    ...getFileBasedOptions(filenameInput.value, lineWrapExts),
    ...getMonacoOptsByCodeEditorConfig(editorConfig),
  });

  filenameInput.addEventListener('input', onInputDebounce(() => {
    const filename = filenameInput.value;
    const previewable = previewableExts.has(extname(filename));
    togglePreviewDisplay(previewable);
    updateEditor(monaco, editor, filename, lineWrapExts);
  }));

  return editor;
}

function getMonacoOptsByCodeEditorConfig(ec: CodeEditorConfig | null): MonacoOpts {
  if (!ec || !isObject(ec)) return {};

  const opts: MonacoOpts = {};
  opts.detectIndentation = !ec.indent_style || !ec.indent_size;

  // with indentSize='tabSize', this also controls the `indentSize` option
  if (!opts.detectIndentation) {
    opts.tabSize = Number(ec.tab_width) || Number(ec.indent_size) || 4;
  }

  opts.trimAutoWhitespace = ec.trim_trailing_whitespace === true;
  opts.insertSpaces = ec.indent_style === 'space';
  opts.useTabStops = ec.indent_style === 'tab';
  return opts;
}
Repository: go-gitea/gitea
File: services/gitdiff/highlightdiff.go (Go)

Code before:
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package gitdiff

import (
	"bytes"
	"html/template"
	"strings"

	"github.com/sergi/go-diff/diffmatchpatch"
)

// extractDiffTokenRemainingFullTag tries to extract full tag with content from the remaining string
// e.g. for input: "content</span>reset", it returns "content</span>", "rest", true
func extractDiffTokenRemainingFullTag(s string) (token, after string, valid bool) {
	pos := 0
	for ; pos < len(s); pos++ {
		c := s[pos]
		if c == '<' {
			break
		}
		// keep in mind: even if we'd like to relax this check,
		// we should never ignore "&" because it is for HTML entity and can't be safely used in the diff algorithm,
		// because diff between "&lt;" and "&gt;" will generate broken result.
		isSymbolChar := 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_' || c == '-'
		if !isSymbolChar {
			return "", s, false
		}
	}
	if pos+1 >= len(s) || s[pos+1] != '/' {
		return "", s, false
	}
	pos2 := strings.IndexByte(s[pos:], '>')
	if pos2 == -1 {
		return "", s, false
	}
	return s[:pos+pos2+1], s[pos+pos2+1:], true
}


Review comment (suggestion):
```suggestion
// e.g. for input: "content</span>reset", it returns "content</span>", "reset", true
```

Code after:
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package gitdiff

import (
	"bytes"
	"html/template"
	"strings"

	"github.com/sergi/go-diff/diffmatchpatch"
)

// extractDiffTokenRemainingFullTag tries to extract full tag with content from the remaining string
// e.g. for input: "content</span>the-rest...", it returns "content</span>", "the-rest...", true
func extractDiffTokenRemainingFullTag(s string) (token, after string, valid bool) {
	pos := 0
	for ; pos < len(s); pos++ {
		c := s[pos]
		if c == '<' {
			break
		}
		// keep in mind: even if we'd like to relax this check,
		// we should never ignore "&" because it is for HTML entity and can't be safely used in the diff algorithm,
		// because diff between "&lt;" and "&gt;" will generate broken result.
		isSymbolChar := 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_' || c == '-'
		if !isSymbolChar {
			return "", s, false
		}
	}
	if pos+1 >= len(s) || s[pos+1] != '/' {
		return "", s, false
	}
	pos2 := strings.IndexByte(s[pos:], '>')
	if pos2 == -1 {
		return "", s, false
	}
	return s[:pos+pos2+1], s[pos+pos2+1:], true
}
Repository: go-gitea/gitea
File: services/gitdiff/highlightdiff.go (Go)

Code before:
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package gitdiff

import (
	"bytes"
	"html/template"
	"strings"

	"github.com/sergi/go-diff/diffmatchpatch"
)

// extractDiffTokenRemainingFullTag tries to extract full tag with content from the remaining string
// e.g. for input: "content</span>rest", it returns "content</span>", "rest", true
func extractDiffTokenRemainingFullTag(s string) (token, after string, valid bool) {
	pos := 0
	for ; pos < len(s); pos++ {
		c := s[pos]
		if c == '<' {
			break
		}
		// keep in mind: even if we'd like to relax this check,
		// we should never ignore "&" because it is for HTML entity and can't be safely used in the diff algorithm,
		// because diff between "&lt;" and "&gt;" will generate broken result.
		isSymbolChar := 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_' || c == '-'
		if !isSymbolChar {
			return "", s, false
		}
	}
	if pos+1 >= len(s) || s[pos+1] != '/' {
		return "", s, false
	}
	pos2 := strings.IndexByte(s[pos:], '>')
	if pos2 == -1 {
		return "", s, false
	}
	return s[:pos+pos2+1], s[pos+pos2+1:], true
}


Review comment (suggestion):
```suggestion
// e.g. for input: "content</span>the-rest...", it returns "content</span>", "the-rest...", true
```

Code after:
// Copyright 2022 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package gitdiff

import (
	"bytes"
	"html/template"
	"strings"

	"github.com/sergi/go-diff/diffmatchpatch"
)

// extractDiffTokenRemainingFullTag tries to extract full tag with content from the remaining string
// e.g. for input: "content</span>the-rest...", it returns "content</span>", "the-rest...", true
func extractDiffTokenRemainingFullTag(s string) (token, after string, valid bool) {
	pos := 0
	for ; pos < len(s); pos++ {
		c := s[pos]
		if c == '<' {
			break
		}
		// keep in mind: even if we'd like to relax this check,
		// we should never ignore "&" because it is for HTML entity and can't be safely used in the diff algorithm,
		// because diff between "&lt;" and "&gt;" will generate broken result.
		isSymbolChar := 'a' <= c && c <= 'z' || 'A' <= c && c <= 'Z' || '0' <= c && c <= '9' || c == '_' || c == '-'
		if !isSymbolChar {
			return "", s, false
		}
	}
	if pos+1 >= len(s) || s[pos+1] != '/' {
		return "", s, false
	}
	pos2 := strings.IndexByte(s[pos:], '>')
	if pos2 == -1 {
		return "", s, false
	}
	return s[:pos+pos2+1], s[pos+pos2+1:], true
}
Repository: go-gitea/gitea
File: models/user/user.go (Go)

Code before:
	}

	return &EmailUserMap{results}, nil
}

// GetUserByEmail returns the user object by given e-mail if exists.
func GetUserByEmail(ctx context.Context, email string) (*User, error) {
	if len(email) == 0 {
		return nil, ErrUserNotExist{Name: email}
	}

	email = strings.ToLower(email)
	// Otherwise, check in alternative list for activated email addresses
	emailAddress := &EmailAddress{LowerEmail: email, IsActivated: true}
	has, err := db.GetEngine(ctx).Get(emailAddress)
	if err != nil {
		return nil, err
	}
	if has {
		return GetUserByID(ctx, emailAddress.UID)
	}

	// Finally, if email address is the protected email address:
	if before, ok := strings.CutSuffix(email, strings.ToLower("@"+setting.Service.NoReplyAddress)); ok {
		// check if the email is in format user+id@noreplyaddress
		username, id, isAlias := strings.Cut(before, "+")
		if isAlias {
			id, err := strconv.ParseInt(id, 10, 64)
			if err != nil {
				return nil, ErrUserNotExist{Name: email}
			}
			return GetUserByID(ctx, id)
		}
		return GetUserByName(ctx, username)
	}

	return nil, ErrUserNotExist{Name: email}
}

// GetUser checks if a user already exists
func GetUser(ctx context.Context, user *User) (bool, error) {
	return db.GetEngine(ctx).Get(user)
}

// GetUserByOpenID returns the user object by given OpenID if exists.
func GetUserByOpenID(ctx context.Context, uri string) (*User, error) {
	if len(uri) == 0 {
		return nil, ErrUserNotExist{Name: uri}
	}

	uri, err := openid.Normalize(uri)

Review comment (refactor):
`"+"` logic duplicates 3 times.

It needs a function like `parseUserEmailToNameID(string) (string, int64)`

Code after:
func parseLocalPartToNameID(localPart string) (string, int64) {
	var id int64
	name, idstr, hasPlus := strings.Cut(localPart, "+")
	if hasPlus {
		id, _ = strconv.ParseInt(idstr, 10, 64)
	}
	return name, id
}

// GetUserByEmail returns the user object by given e-mail if exists.
func GetUserByEmail(ctx context.Context, email string) (*User, error) {
	if len(email) == 0 {
		return nil, ErrUserNotExist{Name: email}
	}

	email = strings.ToLower(email)
	// Otherwise, check in alternative list for activated email addresses
	emailAddress := &EmailAddress{LowerEmail: email, IsActivated: true}
	has, err := db.GetEngine(ctx).Get(emailAddress)
	if err != nil {
		return nil, err
	}
	if has {
		return GetUserByID(ctx, emailAddress.UID)
	}

	// Finally, if email address is the protected email address:
	if localPart, ok := strings.CutSuffix(email, strings.ToLower("@"+setting.Service.NoReplyAddress)); ok {
		name, id := parseLocalPartToNameID(localPart)
		if id != 0 {
			return GetUserByID(ctx, id)
		}
		return GetUserByName(ctx, name)
	}

	return nil, ErrUserNotExist{Name: email}
}

// GetUser checks if a user already exists
func GetUser(ctx context.Context, user *User) (bool, error) {
	return db.GetEngine(ctx).Get(user)
}

// GetUserByOpenID returns the user object by given OpenID if exists.
func GetUserByOpenID(ctx context.Context, uri string) (*User, error) {
	if len(uri) == 0 {
		return nil, ErrUserNotExist{Name: uri}
	}

	uri, err := openid.Normalize(uri)
	if err != nil {
Repository: go-gitea/gitea
File: routers/api/packages/auth.go (Go)

Code before:

// conan and container auth
type Auth struct{}

func (a *Auth) Name() string {
	return "packages"
}

// Verify extracts the user from the Bearer token
// If it's an anonymous session, a ghost user is returned
func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) (*user_model.User, error) {
	packageMeta, err := packages.ParseAuthorizationRequest(req)
	if err != nil {
		log.Trace("ParseAuthorizationToken: %v", err)
		return nil, err
	}

	if packageMeta == nil || packageMeta.UserID == 0 {
		return nil, nil
	}

	var u *user_model.User
	if packageMeta.UserID == user_model.ActionsUserID {
		u = user_model.NewActionsUserWithTaskID(packageMeta.ActionsUserTaskID)
	} else {
		u, err = user_model.GetPossibleUserByID(req.Context(), packageMeta.UserID)
		if err != nil {
			return nil, err
		}
	}

	if packageMeta.Scope != "" {
		store.GetData()["IsApiToken"] = true
		store.GetData()["ApiTokenScope"] = packageMeta.Scope
	}

	return u, nil
}


Review comment (suggestion):
`GetPossibleUserByID` was for "Actions" user.

Since there is a explicit `NewActionsUserWithTaskID` above, here it can use GetUserByID directly

Code after:

// Auth is for conan and container
type Auth struct {
	AllowGhostUser bool
}

func (a *Auth) Name() string {
	return "packages"
}

// Verify extracts the user from the Bearer token
func (a *Auth) Verify(req *http.Request, w http.ResponseWriter, store auth.DataStore, sess auth.SessionStore) (*user_model.User, error) {
	packageMeta, err := packages.ParseAuthorizationRequest(req)
	if err != nil {
		log.Trace("ParseAuthorizationToken: %v", err)
		return nil, err
	}

	if packageMeta == nil || packageMeta.UserID == 0 {
		return nil, nil
	}

	var u *user_model.User
	switch packageMeta.UserID {
	case user_model.GhostUserID:
		if !a.AllowGhostUser {
			return nil, nil
		}
		u = user_model.NewGhostUser()
	case user_model.ActionsUserID:
		u = user_model.NewActionsUserWithTaskID(packageMeta.ActionsUserTaskID)
	default:
		u, err = user_model.GetUserByID(req.Context(), packageMeta.UserID)
		if err != nil {
			return nil, err
		}
	}

	if packageMeta.Scope != "" {
		store.GetData()["IsApiToken"] = true
		store.GetData()["ApiTokenScope"] = packageMeta.Scope
	}

	return u, nil
}
Repository: go-gitea/gitea
File: build/generate-go-licenses.go (Go)

Code before:
	"strings"
)

// regexp is based on go-license, excluding README and NOTICE
// https://github.com/google/go-licenses/blob/master/licenses/find.go
var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)

var excludedExt = map[string]bool{
	".gitignore": true,
	".go":        true,
	".mod":       true,
	".sum":       true,
	".toml":      true,
	".yml":       true,
}

type ModuleInfo struct {
	Path string `json:"Path"`
	Dir  string `json:"Dir"`
	Main bool   `json:"Main"`
}

type LicenseEntry struct {
	Name        string `json:"name"`
	Path        string `json:"path"`
	LicenseText string `json:"licenseText"`
}

func main() {
	if len(os.Args) != 2 {
		fmt.Println("usage: go run generate-go-licenses.go <out-json-file>")
		os.Exit(1)
	}

	out := os.Args[1]

	// Get all modules with their local directory paths from the module cache.
	goCmd := "go"
	if env := os.Getenv("GO"); env != "" {
		goCmd = env
	}
	cmd := exec.Command(goCmd, "list", "-m", "-json", "all")
	cmd.Stderr = os.Stderr
	output, err := cmd.Output()
	if err != nil {
		fmt.Fprintf(os.Stderr, "failed to run 'go list -m -json all': %v\n", err)
		os.Exit(1)
	}

	// Parse streaming JSON (multiple JSON objects concatenated).
	var modules []ModuleInfo

Review comment (suggestion):
```suggestion
	".yaml":       true,
	".yml":       true,
```

Code after:
	"strings"
)

// regexp is based on go-license, excluding README and NOTICE
// https://github.com/google/go-licenses/blob/master/licenses/find.go
var licenseRe = regexp.MustCompile(`^(?i)((UN)?LICEN(S|C)E|COPYING).*$`)

// primaryLicenseRe matches exact primary license filenames without suffixes.
// When a directory has both primary and variant files (e.g. LICENSE and
// LICENSE.docs), only the primary files are kept.
var primaryLicenseRe = regexp.MustCompile(`^(?i)(LICEN[SC]E|COPYING)$`)

// ignoredNames are LicenseEntry.Name values to exclude from the output.
var ignoredNames = map[string]bool{
	"code.gitea.io/gitea":                 true,
	"code.gitea.io/gitea/options/license": true,
}

var excludedExt = map[string]bool{
	".gitignore": true,
	".go":        true,
	".mod":       true,
	".sum":       true,
	".toml":      true,
	".yaml":      true,
	".yml":       true,
}

type ModuleInfo struct {
	Path    string
	Dir     string
	PkgDirs []string // directories of packages imported from this module
}

type LicenseEntry struct {
	Name        string `json:"name"`
	Path        string `json:"path"`
	LicenseText string `json:"licenseText"`
}

// getModules returns all dependency modules with their local directory paths
// and the package directories used from each module.
func getModules(goCmd string) []ModuleInfo {
	cmd := exec.Command(goCmd, "list", "-deps", "-f",
		"{{if .Module}}{{.Module.Path}}\t{{.Module.Dir}}\t{{.Dir}}{{end}}", "./...")
	cmd.Stderr = os.Stderr
	// Use GOOS=linux with CGO to ensure we capture all platform-specific
	// dependencies, matching the CI environment.
	cmd.Env = append(os.Environ(), "GOOS=linux", "GOARCH=amd64", "CGO_ENABLED=1")
	output, err := cmd.Output()
	if err != nil {