<commit_before>// Package nexus is a client for Go code to pull data from a Sonatype Nexus instance. Nexus provides a REST API,
// although some information may require several calls to collate all the data. So this client provides some methods
// to abstract away the necessary plumbing.
package nexus

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"

	"github.com/hanjos/nexus/credentials"
	"github.com/hanjos/nexus/search"
)

// Client accesses a Nexus instance. The default Client should work for the newest Nexus versions. Older Nexus
// versions may need or benefit from a specific client.
type Client interface {
	// Returns all artifacts in this Nexus which satisfy the given criteria.
	Artifacts(criteria search.Criteria) ([]*Artifact, error)

	// Returns all repositories in this Nexus.
	Repositories() ([]*Repository, error)
}

// Nexus2x represents a Nexus v2.x instance. It's the default Client implementation.
type Nexus2x struct {
	Url string // e.g. http://nexus.somewhere.com:8080/nexus

	credentials.Credentials // e.g. credentials.BasicAuth{"username", "password"}
}

// New creates a new Nexus client, using the default Client implementation.
func New(url string, c credentials.Credentials) Client {
	return &Nexus2x{Url: url, Credentials: credentials.OrZero(c)}
}

// builds the proper URL with parameters for GET-ing.
func (nexus Nexus2x) fullUrlFor(query string, filter map[string]string) string {
	params := []string{}

	for k, v := range filter {
		params = append(params, k+"="+v)
	}

	if len(params) == 0 {
		return nexus.Url + "/" + query
	} else {
		return nexus.Url + "/" + query + "?" + strings.Join(params, "&")
	}
}

// does the actual legwork, going to Nexus and validating the response.
func (nexus Nexus2x) fetch(url string, params map[string]string) (*http.Response, error) {
	get, err := http.NewRequest("GET", nexus.fullUrlFor(url, params), nil)
	if err != nil {
		return nil, err
	}

	nexus.Credentials.Sign(get)
	get.Header.Add("Accept", "application/json")

	// go for it!
	response, err := http.DefaultClient.Do(get)
	if err != nil {
		return nil, err
	}

	// for us, 4xx are 5xx are errors, so we need to validate the response
	if 400 <= response.StatusCode && response.StatusCode < 600 {
		return response, &BadResponseError{Url: nexus.Url, StatusCode: response.StatusCode, Status: response.Status}
	}

	// everything alright, carry on
	return response, err
}

func bodyToBytes(body io.ReadCloser) ([]byte, error) {
	buf := new(bytes.Buffer)<commit_msg>Every Nexus2x client uses its own HTTP client, instead of the default.<commit_after>// Package nexus is a client for Go code to pull data from a Sonatype Nexus instance. Nexus provides a REST API,
// although some information may require several calls to collate all the data. So this client provides some methods
// to abstract away the necessary plumbing.
package nexus

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strconv"
	"strings"

	"github.com/hanjos/nexus/credentials"
	"github.com/hanjos/nexus/search"
)

// Client accesses a Nexus instance. The default Client should work for the newest Nexus versions. Older Nexus
// versions may need or benefit from a specific client.
type Client interface {
	// Returns all artifacts in this Nexus which satisfy the given criteria.
	Artifacts(criteria search.Criteria) ([]*Artifact, error)

	// Returns all repositories in this Nexus.
	Repositories() ([]*Repository, error)
}

// Nexus2x represents a Nexus v2.x instance. It's the default Client implementation.
type Nexus2x struct {
	Url string // e.g. http://nexus.somewhere.com:8080/nexus

	credentials.Credentials // e.g. credentials.BasicAuth{"username", "password"}
	HttpClient *http.Client // the network client
}

// New creates a new Nexus client, using the default Client implementation.
func New(url string, c credentials.Credentials) Client {
	return &Nexus2x{Url: url, Credentials: credentials.OrZero(c), HttpClient: &http.Client{}}
}

// builds the proper URL with parameters for GET-ing.
func (nexus Nexus2x) fullUrlFor(query string, filter map[string]string) string {
	params := []string{}

	for k, v := range filter {
		params = append(params, k+"="+v)
	}

	if len(params) == 0 {
		return nexus.Url + "/" + query
	} else {
		return nexus.Url + "/" + query + "?" + strings.Join(params, "&")
	}
}

// does the actual legwork, going to Nexus and validating the response.
func (nexus Nexus2x) fetch(url string, params map[string]string) (*http.Response, error) {
	get, err := http.NewRequest("GET", nexus.fullUrlFor(url, params), nil)
	if err != nil {
		return nil, err
	}

	nexus.Credentials.Sign(get)
	get.Header.Add("Accept", "application/json")

	// go for it!
	response, err := nexus.HttpClient.Do(get)
	if err != nil {
		return nil, err
	}

	// for us, 4xx are 5xx are errors, so we need to validate the response
	if 400 <= response.StatusCode && response.StatusCode < 600 {
		return response, &BadResponseError{Url: nexus.Url, StatusCode: response.StatusCode, Status: response.Status}
	}

	// everything alright, carry on
	return response, err
}

func bodyToBytes(body io.ReadCloser) ([]byte, error) {
	buf := new(bytes.Buffer)
{'fraction_non_alphanumeric': 0.11782826338082403, 'fraction_numerical': 0.007508663842895649, 'mean_word_length': 4.0732421875, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 3, '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': '1704081', 'n_tokens_mistral': 1728, 'n_tokens_neox': 1595, 'n_words': 577}