remove vendor
parent
c1da44fe49
commit
998f6bda7d
@ -1,21 +0,0 @@
|
|||||||
The MIT License (MIT)
|
|
||||||
|
|
||||||
Copyright (c) 2014-2016 Aetrion LLC
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
@ -1,49 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
type AccountsService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Account represents a DNSimple account.
|
|
||||||
type Account struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
PlanIdentifier string `json:"plan_identifier,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func accountsPath() string {
|
|
||||||
return fmt.Sprintf("/accounts")
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccountsResponse represents a response from an API method that returns a collection of Account struct.
|
|
||||||
type AccountsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Account `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListAccounts list the accounts for an user.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/accounts/#list
|
|
||||||
func (s *AccountsService) ListAccounts(options *ListOptions) (*AccountsResponse, error) {
|
|
||||||
path := versioned(accountsPath())
|
|
||||||
accountsResponse := &AccountsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, accountsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return accountsResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
accountsResponse.HttpResponse = resp
|
|
||||||
return accountsResponse, nil
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/base64"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
httpHeaderDomainToken = "X-DNSimple-Domain-Token"
|
|
||||||
httpHeaderApiToken = "X-DNSimple-Token"
|
|
||||||
httpHeaderAuthorization = "Authorization"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Provides credentials that can be used for authenticating with DNSimple.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/#authentication
|
|
||||||
type Credentials interface {
|
|
||||||
// Returns the HTTP headers that should be set
|
|
||||||
// to authenticate the HTTP Request.
|
|
||||||
Headers() map[string]string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain token authentication
|
|
||||||
type domainTokenCredentials struct {
|
|
||||||
domainToken string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewDomainTokenCredentials construct Credentials using the DNSimple Domain Token method.
|
|
||||||
func NewDomainTokenCredentials(domainToken string) Credentials {
|
|
||||||
return &domainTokenCredentials{domainToken: domainToken}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *domainTokenCredentials) Headers() map[string]string {
|
|
||||||
return map[string]string{httpHeaderDomainToken: c.domainToken}
|
|
||||||
}
|
|
||||||
|
|
||||||
// HTTP basic authentication
|
|
||||||
type httpBasicCredentials struct {
|
|
||||||
email string
|
|
||||||
password string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewHTTPBasicCredentials construct Credentials using HTTP Basic Auth.
|
|
||||||
func NewHTTPBasicCredentials(email, password string) Credentials {
|
|
||||||
return &httpBasicCredentials{email, password}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *httpBasicCredentials) Headers() map[string]string {
|
|
||||||
return map[string]string{httpHeaderAuthorization: "Basic " + c.basicAuth(c.email, c.password)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *httpBasicCredentials) basicAuth(username, password string) string {
|
|
||||||
auth := username + ":" + password
|
|
||||||
return base64.StdEncoding.EncodeToString([]byte(auth))
|
|
||||||
}
|
|
||||||
|
|
||||||
// OAuth token authentication
|
|
||||||
|
|
||||||
type oauthTokenCredentials struct {
|
|
||||||
oauthToken string
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewOauthTokenCredentials construct Credentials using the OAuth access token.
|
|
||||||
func NewOauthTokenCredentials(oauthToken string) Credentials {
|
|
||||||
return &oauthTokenCredentials{oauthToken: oauthToken}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *oauthTokenCredentials) Headers() map[string]string {
|
|
||||||
return map[string]string{httpHeaderAuthorization: "Bearer " + c.oauthToken}
|
|
||||||
}
|
|
@ -1,135 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CertificatesService handles communication with the certificate related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/certificates
|
|
||||||
type CertificatesService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Certificate represents a Certificate in DNSimple.
|
|
||||||
type Certificate struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
DomainID int `json:"domain_id,omitempty"`
|
|
||||||
CommonName string `json:"common_name,omitempty"`
|
|
||||||
Years int `json:"years,omitempty"`
|
|
||||||
State string `json:"state,omitempty"`
|
|
||||||
AuthorityIdentifier string `json:"authority_identifier,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
ExpiresOn string `json:"expires_on,omitempty"`
|
|
||||||
CertificateRequest string `json:"csr,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CertificateBundle represents a container for all the PEM-encoded X509 certificate entities,
|
|
||||||
// such as the private key, the server certificate and the intermediate chain.
|
|
||||||
type CertificateBundle struct {
|
|
||||||
// CertificateRequest string `json:"csr,omitempty"`
|
|
||||||
PrivateKey string `json:"private_key,omitempty"`
|
|
||||||
ServerCertificate string `json:"server,omitempty"`
|
|
||||||
RootCertificate string `json:"root,omitempty"`
|
|
||||||
IntermediateCertificates []string `json:"chain,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func certificatePath(accountID, domainIdentifier, certificateID string) string {
|
|
||||||
path := fmt.Sprintf("%v/certificates", domainPath(accountID, domainIdentifier))
|
|
||||||
|
|
||||||
if certificateID != "" {
|
|
||||||
path += fmt.Sprintf("/%v", certificateID)
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// CertificateResponse represents a response from an API method that returns a Certificate struct.
|
|
||||||
type CertificateResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Certificate `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CertificateBundleResponse represents a response from an API method that returns a CertificatBundle struct.
|
|
||||||
type CertificateBundleResponse struct {
|
|
||||||
Response
|
|
||||||
Data *CertificateBundle `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CertificatesResponse represents a response from an API method that returns a collection of Certificate struct.
|
|
||||||
type CertificatesResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Certificate `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListCertificates list the certificates for a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/certificates#list
|
|
||||||
func (s *CertificatesService) ListCertificates(accountID, domainIdentifier string, options *ListOptions) (*CertificatesResponse, error) {
|
|
||||||
path := versioned(certificatePath(accountID, domainIdentifier, ""))
|
|
||||||
certificatesResponse := &CertificatesResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, certificatesResponse)
|
|
||||||
if err != nil {
|
|
||||||
return certificatesResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
certificatesResponse.HttpResponse = resp
|
|
||||||
return certificatesResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCertificate fetches the certificate.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/certificates#get
|
|
||||||
func (s *CertificatesService) GetCertificate(accountID, domainIdentifier string, certificateID int) (*CertificateResponse, error) {
|
|
||||||
path := versioned(certificatePath(accountID, domainIdentifier, strconv.Itoa(certificateID)))
|
|
||||||
certificateResponse := &CertificateResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, certificateResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
certificateResponse.HttpResponse = resp
|
|
||||||
return certificateResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DownloadCertificate download the issued server certificate,
|
|
||||||
// as well the root certificate and the intermediate chain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/certificates#download
|
|
||||||
func (s *CertificatesService) DownloadCertificate(accountID, domainIdentifier string, certificateID int) (*CertificateBundleResponse, error) {
|
|
||||||
path := versioned(certificatePath(accountID, domainIdentifier, strconv.Itoa(certificateID)) + "/download")
|
|
||||||
certificateBundleResponse := &CertificateBundleResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, certificateBundleResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
certificateBundleResponse.HttpResponse = resp
|
|
||||||
return certificateBundleResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetCertificatePrivateKey fetches the certificate private key.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/certificates#get-private-key
|
|
||||||
func (s *CertificatesService) GetCertificatePrivateKey(accountID, domainIdentifier string, certificateID int) (*CertificateBundleResponse, error) {
|
|
||||||
path := versioned(certificatePath(accountID, domainIdentifier, strconv.Itoa(certificateID)) + "/private_key")
|
|
||||||
certificateBundleResponse := &CertificateBundleResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, certificateBundleResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
certificateBundleResponse.HttpResponse = resp
|
|
||||||
return certificateBundleResponse, nil
|
|
||||||
}
|
|
@ -1,97 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Collaborator represents a Collaborator in DNSimple.
|
|
||||||
type Collaborator struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
DomainID int `json:"domain_id,omitempty"`
|
|
||||||
DomainName string `json:"domain_name,omitempty"`
|
|
||||||
UserID int `json:"user_id,omitempty"`
|
|
||||||
UserEmail string `json:"user_email,omitempty"`
|
|
||||||
Invitation bool `json:"invitation,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
AcceptedAt string `json:"accepted_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CollaboratorAttributes represents Collaborator attributes for AddCollaborator operation.
|
|
||||||
type CollaboratorAttributes struct {
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func collaboratorPath(accountID, domainIdentifier, collaboratorID string) string {
|
|
||||||
path := fmt.Sprintf("%v/collaborators", domainPath(accountID, domainIdentifier))
|
|
||||||
|
|
||||||
if collaboratorID != "" {
|
|
||||||
path += fmt.Sprintf("/%v", collaboratorID)
|
|
||||||
}
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// CollaboratorResponse represents a response from an API method that returns a Collaborator struct.
|
|
||||||
type CollaboratorResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Collaborator `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CollaboratorsResponse represents a response from an API method that returns a collection of Collaborator struct.
|
|
||||||
type CollaboratorsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Collaborator `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListCollaborators list the collaborators for a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/collaborators#list
|
|
||||||
func (s *DomainsService) ListCollaborators(accountID, domainIdentifier string, options *ListOptions) (*CollaboratorsResponse, error) {
|
|
||||||
path := versioned(collaboratorPath(accountID, domainIdentifier, ""))
|
|
||||||
collaboratorsResponse := &CollaboratorsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, collaboratorsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return collaboratorsResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
collaboratorsResponse.HttpResponse = resp
|
|
||||||
return collaboratorsResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCollaborator adds a new collaborator to the domain in the account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/collaborators#add
|
|
||||||
func (s *DomainsService) AddCollaborator(accountID string, domainIdentifier string, attributes CollaboratorAttributes) (*CollaboratorResponse, error) {
|
|
||||||
path := versioned(collaboratorPath(accountID, domainIdentifier, ""))
|
|
||||||
collaboratorResponse := &CollaboratorResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, attributes, collaboratorResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
collaboratorResponse.HttpResponse = resp
|
|
||||||
return collaboratorResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RemoveCollaborator PERMANENTLY deletes a domain from the account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/collaborators#add
|
|
||||||
func (s *DomainsService) RemoveCollaborator(accountID string, domainIdentifier string, collaboratorID string) (*CollaboratorResponse, error) {
|
|
||||||
path := versioned(collaboratorPath(accountID, domainIdentifier, collaboratorID))
|
|
||||||
collaboratorResponse := &CollaboratorResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
collaboratorResponse.HttpResponse = resp
|
|
||||||
return collaboratorResponse, nil
|
|
||||||
}
|
|
@ -1,139 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ContactsService handles communication with the contact related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/contacts/
|
|
||||||
type ContactsService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contact represents a Contact in DNSimple.
|
|
||||||
type Contact struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
AccountID int `json:"account_id,omitempty"`
|
|
||||||
Label string `json:"label,omitempty"`
|
|
||||||
FirstName string `json:"first_name,omitempty"`
|
|
||||||
LastName string `json:"last_name,omitempty"`
|
|
||||||
JobTitle string `json:"job_title,omitempty"`
|
|
||||||
Organization string `json:"organization_name,omitempty"`
|
|
||||||
Address1 string `json:"address1,omitempty"`
|
|
||||||
Address2 string `json:"address2,omitempty"`
|
|
||||||
City string `json:"city,omitempty"`
|
|
||||||
StateProvince string `json:"state_province,omitempty"`
|
|
||||||
PostalCode string `json:"postal_code,omitempty"`
|
|
||||||
Country string `json:"country,omitempty"`
|
|
||||||
Phone string `json:"phone,omitempty"`
|
|
||||||
Fax string `json:"fax,omitempty"`
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func contactPath(accountID string, contact interface{}) string {
|
|
||||||
if contact != nil {
|
|
||||||
return fmt.Sprintf("/%v/contacts/%v", accountID, contact)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("/%v/contacts", accountID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContactResponse represents a response from an API method that returns a Contact struct.
|
|
||||||
type ContactResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Contact `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ContactsResponse represents a response from an API method that returns a collection of Contact struct.
|
|
||||||
type ContactsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Contact `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListContacts list the contacts for an account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/contacts/#list
|
|
||||||
func (s *ContactsService) ListContacts(accountID string, options *ListOptions) (*ContactsResponse, error) {
|
|
||||||
path := versioned(contactPath(accountID, nil))
|
|
||||||
contactsResponse := &ContactsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, contactsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return contactsResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contactsResponse.HttpResponse = resp
|
|
||||||
return contactsResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateContact creates a new contact.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/contacts/#create
|
|
||||||
func (s *ContactsService) CreateContact(accountID string, contactAttributes Contact) (*ContactResponse, error) {
|
|
||||||
path := versioned(contactPath(accountID, nil))
|
|
||||||
contactResponse := &ContactResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, contactAttributes, contactResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contactResponse.HttpResponse = resp
|
|
||||||
return contactResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetContact fetches a contact.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/contacts/#get
|
|
||||||
func (s *ContactsService) GetContact(accountID string, contactID int) (*ContactResponse, error) {
|
|
||||||
path := versioned(contactPath(accountID, contactID))
|
|
||||||
contactResponse := &ContactResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, contactResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contactResponse.HttpResponse = resp
|
|
||||||
return contactResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateContact updates a contact.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/contacts/#update
|
|
||||||
func (s *ContactsService) UpdateContact(accountID string, contactID int, contactAttributes Contact) (*ContactResponse, error) {
|
|
||||||
path := versioned(contactPath(accountID, contactID))
|
|
||||||
contactResponse := &ContactResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.patch(path, contactAttributes, contactResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contactResponse.HttpResponse = resp
|
|
||||||
return contactResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteContact PERMANENTLY deletes a contact from the account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/contacts/#delete
|
|
||||||
func (s *ContactsService) DeleteContact(accountID string, contactID int) (*ContactResponse, error) {
|
|
||||||
path := versioned(contactPath(accountID, contactID))
|
|
||||||
contactResponse := &ContactResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
contactResponse.HttpResponse = resp
|
|
||||||
return contactResponse, nil
|
|
||||||
}
|
|
@ -1,341 +0,0 @@
|
|||||||
// Package dnsimple provides a client for the DNSimple API.
|
|
||||||
// In order to use this package you will need a DNSimple account.
|
|
||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"log"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/google/go-querystring/query"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
// libraryVersion identifies the current library version.
|
|
||||||
// This is a pro-forma convention given that Go dependencies
|
|
||||||
// tends to be fetched directly from the repo.
|
|
||||||
// It is also used in the user-agent identify the client.
|
|
||||||
libraryVersion = "0.13.0"
|
|
||||||
|
|
||||||
// defaultBaseURL to the DNSimple production API.
|
|
||||||
defaultBaseURL = "https://api.dnsimple.com"
|
|
||||||
|
|
||||||
// userAgent represents the default user agent used
|
|
||||||
// when no other user agent is set.
|
|
||||||
defaultUserAgent = "dnsimple-go/" + libraryVersion
|
|
||||||
|
|
||||||
apiVersion = "v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Client represents a client to the DNSimple API.
|
|
||||||
type Client struct {
|
|
||||||
// HttpClient is the underlying HTTP client
|
|
||||||
// used to communicate with the API.
|
|
||||||
HttpClient *http.Client
|
|
||||||
|
|
||||||
// Credentials used for accessing the DNSimple API
|
|
||||||
Credentials Credentials
|
|
||||||
|
|
||||||
// BaseURL for API requests.
|
|
||||||
// Defaults to the public DNSimple API, but can be set to a different endpoint (e.g. the sandbox).
|
|
||||||
BaseURL string
|
|
||||||
|
|
||||||
// UserAgent used when communicating with the DNSimple API.
|
|
||||||
UserAgent string
|
|
||||||
|
|
||||||
// Services used for talking to different parts of the DNSimple API.
|
|
||||||
Identity *IdentityService
|
|
||||||
Accounts *AccountsService
|
|
||||||
Certificates *CertificatesService
|
|
||||||
Contacts *ContactsService
|
|
||||||
Domains *DomainsService
|
|
||||||
Oauth *OauthService
|
|
||||||
Registrar *RegistrarService
|
|
||||||
Services *ServicesService
|
|
||||||
Templates *TemplatesService
|
|
||||||
Tlds *TldsService
|
|
||||||
VanityNameServers *VanityNameServersService
|
|
||||||
Webhooks *WebhooksService
|
|
||||||
Zones *ZonesService
|
|
||||||
|
|
||||||
// Set to true to output debugging logs during API calls
|
|
||||||
Debug bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListOptions contains the common options you can pass to a List method
|
|
||||||
// in order to control parameters such as paginations and page number.
|
|
||||||
type ListOptions struct {
|
|
||||||
// The page to return
|
|
||||||
Page int `url:"page,omitempty"`
|
|
||||||
|
|
||||||
// The number of entries to return per page
|
|
||||||
PerPage int `url:"per_page,omitempty"`
|
|
||||||
|
|
||||||
// The order criteria to sort the results.
|
|
||||||
// The value is a comma-separated list of field[:direction],
|
|
||||||
// eg. name | name:desc | name:desc,expiration:desc
|
|
||||||
Sort string `url:"sort,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewClient returns a new DNSimple API client using the given credentials.
|
|
||||||
func NewClient(credentials Credentials) *Client {
|
|
||||||
c := &Client{Credentials: credentials, HttpClient: &http.Client{}, BaseURL: defaultBaseURL}
|
|
||||||
c.Identity = &IdentityService{client: c}
|
|
||||||
c.Accounts = &AccountsService{client: c}
|
|
||||||
c.Certificates = &CertificatesService{client: c}
|
|
||||||
c.Contacts = &ContactsService{client: c}
|
|
||||||
c.Domains = &DomainsService{client: c}
|
|
||||||
c.Oauth = &OauthService{client: c}
|
|
||||||
c.Registrar = &RegistrarService{client: c}
|
|
||||||
c.Services = &ServicesService{client: c}
|
|
||||||
c.Templates = &TemplatesService{client: c}
|
|
||||||
c.Tlds = &TldsService{client: c}
|
|
||||||
c.VanityNameServers = &VanityNameServersService{client: c}
|
|
||||||
c.Webhooks = &WebhooksService{client: c}
|
|
||||||
c.Zones = &ZonesService{client: c}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewRequest creates an API request.
|
|
||||||
// The path is expected to be a relative path and will be resolved
|
|
||||||
// according to the BaseURL of the Client. Paths should always be specified without a preceding slash.
|
|
||||||
func (c *Client) NewRequest(method, path string, payload interface{}) (*http.Request, error) {
|
|
||||||
url := c.BaseURL + path
|
|
||||||
|
|
||||||
body := new(bytes.Buffer)
|
|
||||||
if payload != nil {
|
|
||||||
err := json.NewEncoder(body).Encode(payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
req, err := http.NewRequest(method, url, body)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
|
||||||
req.Header.Add("Accept", "application/json")
|
|
||||||
req.Header.Add("User-Agent", formatUserAgent(c.UserAgent))
|
|
||||||
for key, value := range c.Credentials.Headers() {
|
|
||||||
req.Header.Add(key, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
return req, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatUserAgent builds the final user agent to use for HTTP requests.
|
|
||||||
//
|
|
||||||
// If no custom user agent is provided, the default user agent is used.
|
|
||||||
//
|
|
||||||
// dnsimple-go/1.0
|
|
||||||
//
|
|
||||||
// If a custom user agent is provided, the final user agent is the combination of the custom user agent
|
|
||||||
// prepended by the default user agent.
|
|
||||||
//
|
|
||||||
// dnsimple-go/1.0 customAgentFlag
|
|
||||||
//
|
|
||||||
func formatUserAgent(customUserAgent string) string {
|
|
||||||
if customUserAgent == "" {
|
|
||||||
return defaultUserAgent
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%s %s", defaultUserAgent, customUserAgent)
|
|
||||||
}
|
|
||||||
|
|
||||||
func versioned(path string) string {
|
|
||||||
return fmt.Sprintf("/%s/%s", apiVersion, strings.Trim(path, "/"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) get(path string, obj interface{}) (*http.Response, error) {
|
|
||||||
req, err := c.NewRequest("GET", path, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Do(req, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) post(path string, payload, obj interface{}) (*http.Response, error) {
|
|
||||||
req, err := c.NewRequest("POST", path, payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Do(req, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) put(path string, payload, obj interface{}) (*http.Response, error) {
|
|
||||||
req, err := c.NewRequest("PUT", path, payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Do(req, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) patch(path string, payload, obj interface{}) (*http.Response, error) {
|
|
||||||
req, err := c.NewRequest("PATCH", path, payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Do(req, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Client) delete(path string, payload interface{}, obj interface{}) (*http.Response, error) {
|
|
||||||
req, err := c.NewRequest("DELETE", path, payload)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.Do(req, obj)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do sends an API request and returns the API response.
|
|
||||||
//
|
|
||||||
// The API response is JSON decoded and stored in the value pointed by obj,
|
|
||||||
// or returned as an error if an API error has occurred.
|
|
||||||
// If obj implements the io.Writer interface, the raw response body will be written to obj,
|
|
||||||
// without attempting to decode it.
|
|
||||||
func (c *Client) Do(req *http.Request, obj interface{}) (*http.Response, error) {
|
|
||||||
if c.Debug {
|
|
||||||
log.Printf("Executing request (%v): %#v", req.URL, req)
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := c.HttpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if c.Debug {
|
|
||||||
log.Printf("Response received: %#v", resp)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = CheckResponse(resp)
|
|
||||||
if err != nil {
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If obj implements the io.Writer,
|
|
||||||
// the response body is decoded into v.
|
|
||||||
if obj != nil {
|
|
||||||
if w, ok := obj.(io.Writer); ok {
|
|
||||||
io.Copy(w, resp.Body)
|
|
||||||
} else {
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(obj)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return resp, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// A Response represents an API response.
|
|
||||||
type Response struct {
|
|
||||||
// HTTP response
|
|
||||||
HttpResponse *http.Response
|
|
||||||
|
|
||||||
// If the response is paginated, the Pagination will store them.
|
|
||||||
Pagination *Pagination `json:"pagination"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RateLimit returns the maximum amount of requests this account can send in an hour.
|
|
||||||
func (r *Response) RateLimit() int {
|
|
||||||
value, _ := strconv.Atoi(r.HttpResponse.Header.Get("X-RateLimit-Limit"))
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
// RateLimitRemaining returns the remaining amount of requests this account can send within this hour window.
|
|
||||||
func (r *Response) RateLimitRemaining() int {
|
|
||||||
value, _ := strconv.Atoi(r.HttpResponse.Header.Get("X-RateLimit-Remaining"))
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
|
|
||||||
// RateLimitReset returns when the throttling window will be reset for this account.
|
|
||||||
func (r *Response) RateLimitReset() time.Time {
|
|
||||||
value, _ := strconv.ParseInt(r.HttpResponse.Header.Get("X-RateLimit-Reset"), 10, 64)
|
|
||||||
return time.Unix(value, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the response is paginated, Pagination represents the pagination information.
|
|
||||||
type Pagination struct {
|
|
||||||
CurrentPage int `json:"current_page"`
|
|
||||||
PerPage int `json:"per_page"`
|
|
||||||
TotalPages int `json:"total_pages"`
|
|
||||||
TotalEntries int `json:"total_entries"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// An ErrorResponse represents an API response that generated an error.
|
|
||||||
type ErrorResponse struct {
|
|
||||||
Response
|
|
||||||
|
|
||||||
// human-readable message
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (r *ErrorResponse) Error() string {
|
|
||||||
return fmt.Sprintf("%v %v: %v %v",
|
|
||||||
r.HttpResponse.Request.Method, r.HttpResponse.Request.URL,
|
|
||||||
r.HttpResponse.StatusCode, r.Message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckResponse checks the API response for errors, and returns them if present.
|
|
||||||
// A response is considered an error if the status code is different than 2xx. Specific requests
|
|
||||||
// may have additional requirements, but this is sufficient in most of the cases.
|
|
||||||
func CheckResponse(resp *http.Response) error {
|
|
||||||
if code := resp.StatusCode; 200 <= code && code <= 299 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
errorResponse := &ErrorResponse{}
|
|
||||||
errorResponse.HttpResponse = resp
|
|
||||||
|
|
||||||
err := json.NewDecoder(resp.Body).Decode(errorResponse)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
return errorResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
// addOptions adds the parameters in opt as URL query parameters to s. opt
|
|
||||||
// must be a struct whose fields may contain "url" tags.
|
|
||||||
func addURLQueryOptions(path string, options interface{}) (string, error) {
|
|
||||||
opt := reflect.ValueOf(options)
|
|
||||||
|
|
||||||
// options is a pointer
|
|
||||||
// return if the value of the pointer is nil,
|
|
||||||
if opt.Kind() == reflect.Ptr && opt.IsNil() {
|
|
||||||
return path, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// append the options to the URL
|
|
||||||
u, err := url.Parse(path)
|
|
||||||
if err != nil {
|
|
||||||
return path, err
|
|
||||||
}
|
|
||||||
|
|
||||||
qs, err := query.Values(options)
|
|
||||||
if err != nil {
|
|
||||||
return path, err
|
|
||||||
}
|
|
||||||
|
|
||||||
uqs := u.Query()
|
|
||||||
for k, _ := range qs {
|
|
||||||
uqs.Set(k, qs.Get(k))
|
|
||||||
}
|
|
||||||
u.RawQuery = uqs.Encode()
|
|
||||||
|
|
||||||
return u.String(), nil
|
|
||||||
}
|
|
@ -1,161 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DomainsService handles communication with the domain related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/
|
|
||||||
type DomainsService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Domain represents a domain in DNSimple.
|
|
||||||
type Domain struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
AccountID int `json:"account_id,omitempty"`
|
|
||||||
RegistrantID int `json:"registrant_id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
UnicodeName string `json:"unicode_name,omitempty"`
|
|
||||||
Token string `json:"token,omitempty"`
|
|
||||||
State string `json:"state,omitempty"`
|
|
||||||
AutoRenew bool `json:"auto_renew,omitempty"`
|
|
||||||
PrivateWhois bool `json:"private_whois,omitempty"`
|
|
||||||
ExpiresOn string `json:"expires_on,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainListOptions specifies the optional parameters you can provide
|
|
||||||
// to customize the DomainsService.ListDomains method.
|
|
||||||
type DomainListOptions struct {
|
|
||||||
// Select domains where the name contains given string.
|
|
||||||
NameLike string `url:"name_like,omitempty"`
|
|
||||||
|
|
||||||
// Select domains where the registrant matches given ID.
|
|
||||||
RegistrantID int `url:"registrant_id,omitempty"`
|
|
||||||
|
|
||||||
ListOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainResponse represents a response from an API method that returns a Domain struct.
|
|
||||||
type DomainResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Domain `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainsResponse represents a response from an API method that returns a collection of Domain struct.
|
|
||||||
type DomainsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Domain `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// domainRequest represents a generic wrapper for a domain request,
|
|
||||||
// when domainWrapper cannot be used because of type constraint on Domain.
|
|
||||||
type domainRequest struct {
|
|
||||||
Domain interface{} `json:"domain"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func domainIdentifier(value interface{}) string {
|
|
||||||
switch value := value.(type) {
|
|
||||||
case string:
|
|
||||||
return value
|
|
||||||
case int:
|
|
||||||
return fmt.Sprintf("%d", value)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func domainPath(accountID string, domain interface{}) string {
|
|
||||||
if domain != nil {
|
|
||||||
return fmt.Sprintf("/%v/domains/%v", accountID, domainIdentifier(domain))
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("/%v/domains", accountID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListDomains lists the domains for an account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/#list
|
|
||||||
func (s *DomainsService) ListDomains(accountID string, options *DomainListOptions) (*DomainsResponse, error) {
|
|
||||||
path := versioned(domainPath(accountID, nil))
|
|
||||||
domainsResponse := &DomainsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, domainsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainsResponse.HttpResponse = resp
|
|
||||||
return domainsResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateDomain creates a new domain in the account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/#create
|
|
||||||
func (s *DomainsService) CreateDomain(accountID string, domainAttributes Domain) (*DomainResponse, error) {
|
|
||||||
path := versioned(domainPath(accountID, nil))
|
|
||||||
domainResponse := &DomainResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, domainAttributes, domainResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainResponse.HttpResponse = resp
|
|
||||||
return domainResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDomain fetches a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/#get
|
|
||||||
func (s *DomainsService) GetDomain(accountID string, domain interface{}) (*DomainResponse, error) {
|
|
||||||
path := versioned(domainPath(accountID, domain))
|
|
||||||
domainResponse := &DomainResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, domainResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainResponse.HttpResponse = resp
|
|
||||||
return domainResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteDomain PERMANENTLY deletes a domain from the account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/#delete
|
|
||||||
func (s *DomainsService) DeleteDomain(accountID string, domain interface{}) (*DomainResponse, error) {
|
|
||||||
path := versioned(domainPath(accountID, domain))
|
|
||||||
domainResponse := &DomainResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainResponse.HttpResponse = resp
|
|
||||||
return domainResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ResetDomainToken resets the domain token.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/#reset-token
|
|
||||||
func (s *DomainsService) ResetDomainToken(accountID string, domain interface{}) (*DomainResponse, error) {
|
|
||||||
path := versioned(domainPath(accountID, domain) + "/token")
|
|
||||||
domainResponse := &DomainResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, nil, domainResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainResponse.HttpResponse = resp
|
|
||||||
return domainResponse, nil
|
|
||||||
}
|
|
@ -1,106 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EmailForward represents an email forward in DNSimple.
|
|
||||||
type EmailForward struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
DomainID int `json:"domain_id,omitempty"`
|
|
||||||
From string `json:"from,omitempty"`
|
|
||||||
To string `json:"to,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmailForwardResponse represents a response from an API method that returns an EmailForward struct.
|
|
||||||
type EmailForwardResponse struct {
|
|
||||||
Response
|
|
||||||
Data *EmailForward `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// EmailForwardsResponse represents a response from an API method that returns a collection of EmailForward struct.
|
|
||||||
type EmailForwardsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []EmailForward `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func emailForwardPath(accountID string, domain interface{}, forwardID int) string {
|
|
||||||
path := fmt.Sprintf("%v/email_forwards", domainPath(accountID, domain))
|
|
||||||
|
|
||||||
if forwardID != 0 {
|
|
||||||
path += fmt.Sprintf("/%d", forwardID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListEmailForwards lists the email forwards for a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/email-forwards/#list
|
|
||||||
func (s *DomainsService) ListEmailForwards(accountID string, domain interface{}, options *ListOptions) (*EmailForwardsResponse, error) {
|
|
||||||
path := versioned(emailForwardPath(accountID, domain, 0))
|
|
||||||
forwardsResponse := &EmailForwardsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, forwardsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
forwardsResponse.HttpResponse = resp
|
|
||||||
return forwardsResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateEmailForward creates a new email forward.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/email-forwards/#create
|
|
||||||
func (s *DomainsService) CreateEmailForward(accountID string, domain interface{}, forwardAttributes EmailForward) (*EmailForwardResponse, error) {
|
|
||||||
path := versioned(emailForwardPath(accountID, domain, 0))
|
|
||||||
forwardResponse := &EmailForwardResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, forwardAttributes, forwardResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
forwardResponse.HttpResponse = resp
|
|
||||||
return forwardResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetEmailForward fetches an email forward.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/email-forwards/#get
|
|
||||||
func (s *DomainsService) GetEmailForward(accountID string, domain interface{}, forwardID int) (*EmailForwardResponse, error) {
|
|
||||||
path := versioned(emailForwardPath(accountID, domain, forwardID))
|
|
||||||
forwardResponse := &EmailForwardResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, forwardResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
forwardResponse.HttpResponse = resp
|
|
||||||
return forwardResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteEmailForward PERMANENTLY deletes an email forward from the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/email-forwards/#delete
|
|
||||||
func (s *DomainsService) DeleteEmailForward(accountID string, domain interface{}, forwardID int) (*EmailForwardResponse, error) {
|
|
||||||
path := versioned(emailForwardPath(accountID, domain, forwardID))
|
|
||||||
forwardResponse := &EmailForwardResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
forwardResponse.HttpResponse = resp
|
|
||||||
return forwardResponse, nil
|
|
||||||
}
|
|
@ -1,117 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// DomainPush represents a domain push in DNSimple.
|
|
||||||
type DomainPush struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
DomainID int `json:"domain_id,omitempty"`
|
|
||||||
ContactID int `json:"contact_id,omitempty"`
|
|
||||||
AccountID int `json:"account_id,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
AcceptedAt string `json:"accepted_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainPushAttributes represent a domain push payload (see initiate).
|
|
||||||
type DomainPushAttributes struct {
|
|
||||||
NewAccountEmail string `json:"new_account_email,omitempty"`
|
|
||||||
ContactID string `json:"contact_id,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainPushResponse represents a response from an API method that returns a DomainPush struct.
|
|
||||||
type DomainPushResponse struct {
|
|
||||||
Response
|
|
||||||
Data *DomainPush `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainPushesResponse represents a response from an API method that returns a collection of DomainPush struct.
|
|
||||||
type DomainPushesResponse struct {
|
|
||||||
Response
|
|
||||||
Data []DomainPush `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func initiateDomainPushPath(accountID string, domainID string) string {
|
|
||||||
return fmt.Sprintf("%v/pushes", domainPath(accountID, domainID))
|
|
||||||
}
|
|
||||||
|
|
||||||
func domainPushPath(accountID string, pushID int) string {
|
|
||||||
path := fmt.Sprintf("%v/pushes", accountID)
|
|
||||||
|
|
||||||
if pushID != 0 {
|
|
||||||
path += fmt.Sprintf("/%d", pushID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// InitiatePush initiate a new domain push.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/pushes/#initiate
|
|
||||||
func (s *DomainsService) InitiatePush(accountID string, domainID string, pushAttributes DomainPushAttributes) (*DomainPushResponse, error) {
|
|
||||||
path := versioned(initiateDomainPushPath(accountID, domainID))
|
|
||||||
pushResponse := &DomainPushResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, pushAttributes, pushResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pushResponse.HttpResponse = resp
|
|
||||||
return pushResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListPushes lists the pushes for an account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/pushes/#list
|
|
||||||
func (s *DomainsService) ListPushes(accountID string, options *ListOptions) (*DomainPushesResponse, error) {
|
|
||||||
path := versioned(domainPushPath(accountID, 0))
|
|
||||||
pushesResponse := &DomainPushesResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, pushesResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pushesResponse.HttpResponse = resp
|
|
||||||
return pushesResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// AcceptPush accept a push for a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/pushes/#accept
|
|
||||||
func (s *DomainsService) AcceptPush(accountID string, pushID int, pushAttributes DomainPushAttributes) (*DomainPushResponse, error) {
|
|
||||||
path := versioned(domainPushPath(accountID, pushID))
|
|
||||||
pushResponse := &DomainPushResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, pushAttributes, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pushResponse.HttpResponse = resp
|
|
||||||
return pushResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RejectPush reject a push for a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/domains/pushes/#reject
|
|
||||||
func (s *DomainsService) RejectPush(accountID string, pushID int) (*DomainPushResponse, error) {
|
|
||||||
path := versioned(domainPushPath(accountID, pushID))
|
|
||||||
pushResponse := &DomainPushResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
pushResponse.HttpResponse = resp
|
|
||||||
return pushResponse, nil
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
// IdentityService handles communication with several authentication identity
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/identity/
|
|
||||||
type IdentityService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhoamiData represents an authenticated context
|
|
||||||
// that contains information about the current logged User and/or Account.
|
|
||||||
type WhoamiData struct {
|
|
||||||
User *User `json:"user,omitempty"`
|
|
||||||
Account *Account `json:"account,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhoamiResponse represents a response from an API method that returns a Whoami struct.
|
|
||||||
type WhoamiResponse struct {
|
|
||||||
Response
|
|
||||||
Data *WhoamiData `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whoami gets the current authenticate context.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/whoami
|
|
||||||
func (s *IdentityService) Whoami() (*WhoamiResponse, error) {
|
|
||||||
path := versioned("/whoami")
|
|
||||||
whoamiResponse := &WhoamiResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, whoamiResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
whoamiResponse.HttpResponse = resp
|
|
||||||
return whoamiResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Whoami is a state-less shortcut to client.Whoami()
|
|
||||||
// that returns only the relevant Data.
|
|
||||||
func Whoami(c *Client) (data *WhoamiData, err error) {
|
|
||||||
resp, err := c.Identity.Whoami()
|
|
||||||
if resp != nil {
|
|
||||||
data = resp.Data
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
@ -1,113 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"net/url"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// GrantType is a string that identifies a particular grant type in the exchange request.
|
|
||||||
type GrantType string
|
|
||||||
|
|
||||||
const (
|
|
||||||
// AuthorizationCodeGrant is the type of access token request
|
|
||||||
// for an Authorization Code Grant flow.
|
|
||||||
// https://tools.ietf.org/html/rfc6749#section-4.1
|
|
||||||
AuthorizationCodeGrant = GrantType("authorization_code")
|
|
||||||
)
|
|
||||||
|
|
||||||
// OauthService handles communication with the authorization related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/oauth/
|
|
||||||
type OauthService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// AccessToken represents a DNSimple Oauth access token.
|
|
||||||
type AccessToken struct {
|
|
||||||
Token string `json:"access_token"`
|
|
||||||
Type string `json:"token_type"`
|
|
||||||
AccountID int `json:"account_id"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExchangeAuthorizationRequest represents a request to exchange
|
|
||||||
// an authorization code for an access token.
|
|
||||||
// RedirectURI is optional, all the other fields are mandatory.
|
|
||||||
type ExchangeAuthorizationRequest struct {
|
|
||||||
Code string `json:"code"`
|
|
||||||
ClientID string `json:"client_id"`
|
|
||||||
ClientSecret string `json:"client_secret"`
|
|
||||||
RedirectURI string `json:"redirect_uri,omitempty"`
|
|
||||||
State string `json:"state,omitempty"`
|
|
||||||
GrantType GrantType `json:"grant_type,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExchangeAuthorizationError represents a failed request to exchange
|
|
||||||
// an authorization code for an access token.
|
|
||||||
type ExchangeAuthorizationError struct {
|
|
||||||
// HTTP response
|
|
||||||
HttpResponse *http.Response
|
|
||||||
|
|
||||||
ErrorCode string `json:"error"`
|
|
||||||
ErrorDescription string `json:"error_description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (r *ExchangeAuthorizationError) Error() string {
|
|
||||||
return fmt.Sprintf("%v %v: %v %v",
|
|
||||||
r.HttpResponse.Request.Method, r.HttpResponse.Request.URL,
|
|
||||||
r.ErrorCode, r.ErrorDescription)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExchangeAuthorizationForToken exchanges the short-lived authorization code for an access token
|
|
||||||
// you can use to authenticate your API calls.
|
|
||||||
func (s *OauthService) ExchangeAuthorizationForToken(authorization *ExchangeAuthorizationRequest) (*AccessToken, error) {
|
|
||||||
path := versioned("/oauth/access_token")
|
|
||||||
|
|
||||||
req, err := s.client.NewRequest("POST", path, authorization)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.HttpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
defer resp.Body.Close()
|
|
||||||
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
errorResponse := &ExchangeAuthorizationError{}
|
|
||||||
errorResponse.HttpResponse = resp
|
|
||||||
json.NewDecoder(resp.Body).Decode(errorResponse)
|
|
||||||
return nil, errorResponse
|
|
||||||
}
|
|
||||||
|
|
||||||
accessToken := &AccessToken{}
|
|
||||||
err = json.NewDecoder(resp.Body).Decode(accessToken)
|
|
||||||
|
|
||||||
return accessToken, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthorizationOptions represents the option you can use to generate an authorization URL.
|
|
||||||
type AuthorizationOptions struct {
|
|
||||||
RedirectURI string `url:"redirect_uri,omitempty"`
|
|
||||||
// A randomly generated string to verify the validity of the request.
|
|
||||||
// Currently "state" is required by the DNSimple OAuth implementation, so you must specify it.
|
|
||||||
State string `url:"state,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AuthorizeURL generates the URL to authorize an user for an application via the OAuth2 flow.
|
|
||||||
func (s *OauthService) AuthorizeURL(clientID string, options *AuthorizationOptions) string {
|
|
||||||
uri, _ := url.Parse(strings.Replace(s.client.BaseURL, "api.", "", 1))
|
|
||||||
uri.Path = "/oauth/authorize"
|
|
||||||
query := uri.Query()
|
|
||||||
query.Add("client_id", clientID)
|
|
||||||
query.Add("response_type", "code")
|
|
||||||
uri.RawQuery = query.Encode()
|
|
||||||
|
|
||||||
path, _ := addURLQueryOptions(uri.String(), options)
|
|
||||||
return path
|
|
||||||
}
|
|
@ -1,170 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// RegistrarService handles communication with the registrar related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/
|
|
||||||
type RegistrarService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainCheck represents the result of a domain check.
|
|
||||||
type DomainCheck struct {
|
|
||||||
Domain string `json:"domain"`
|
|
||||||
Available bool `json:"available"`
|
|
||||||
Premium bool `json:"premium"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainCheckResponse represents a response from the domain check.
|
|
||||||
type DomainCheckResponse struct {
|
|
||||||
Response
|
|
||||||
Data *DomainCheck `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// CheckDomain checks a domain name.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/#check
|
|
||||||
func (s *RegistrarService) CheckDomain(accountID string, domainName string) (*DomainCheckResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/check", accountID, domainName))
|
|
||||||
checkResponse := &DomainCheckResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, checkResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
checkResponse.HttpResponse = resp
|
|
||||||
return checkResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainRegisterRequest represents the attributes you can pass to a register API request.
|
|
||||||
// Some attributes are mandatory.
|
|
||||||
type DomainRegisterRequest struct {
|
|
||||||
// The ID of the Contact to use as registrant for the domain
|
|
||||||
RegistrantID int `json:"registrant_id"`
|
|
||||||
// Set to true to enable the whois privacy service. An extra cost may apply.
|
|
||||||
// Default to false.
|
|
||||||
EnableWhoisPrivacy bool `json:"private_whois,omitempty"`
|
|
||||||
// Set to true to enable the auto-renewal of the domain.
|
|
||||||
// Default to true.
|
|
||||||
EnableAutoRenewal bool `json:"auto_renew,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainRegistrationResponse represents a response from an API method that results in a domain registration.
|
|
||||||
type DomainRegistrationResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Domain `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RegisterDomain registers a domain name.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/#register
|
|
||||||
func (s *RegistrarService) RegisterDomain(accountID string, domainName string, request *DomainRegisterRequest) (*DomainRegistrationResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/registration", accountID, domainName))
|
|
||||||
registrationResponse := &DomainRegistrationResponse{}
|
|
||||||
|
|
||||||
// TODO: validate mandatory attributes RegistrantID
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, request, registrationResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
registrationResponse.HttpResponse = resp
|
|
||||||
return registrationResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainTransferRequest represents the attributes you can pass to a transfer API request.
|
|
||||||
// Some attributes are mandatory.
|
|
||||||
type DomainTransferRequest struct {
|
|
||||||
// The ID of the Contact to use as registrant for the domain
|
|
||||||
RegistrantID int `json:"registrant_id"`
|
|
||||||
// The Auth-Code required to transfer the domain.
|
|
||||||
// This is provided by the current registrar of the domain.
|
|
||||||
AuthCode string `json:"auth_code,omitempty"`
|
|
||||||
// Set to true to enable the whois privacy service. An extra cost may apply.
|
|
||||||
// Default to false.
|
|
||||||
EnableWhoisPrivacy bool `json:"private_whois,omitempty"`
|
|
||||||
// Set to true to enable the auto-renewal of the domain.
|
|
||||||
// Default to true.
|
|
||||||
EnableAutoRenewal bool `json:"auto_renew,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainTransferResponse represents a response from an API method that results in a domain transfer.
|
|
||||||
type DomainTransferResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Domain `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TransferDomain transfers a domain name.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/#transfer
|
|
||||||
func (s *RegistrarService) TransferDomain(accountID string, domainName string, request *DomainTransferRequest) (*DomainTransferResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/transfer", accountID, domainName))
|
|
||||||
transferResponse := &DomainTransferResponse{}
|
|
||||||
|
|
||||||
// TODO: validate mandatory attributes RegistrantID
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, request, transferResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
transferResponse.HttpResponse = resp
|
|
||||||
return transferResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainTransferOutResponse represents a response from an API method that results in a domain transfer out.
|
|
||||||
type DomainTransferOutResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Domain `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transfer out a domain name.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/#transfer-out
|
|
||||||
func (s *RegistrarService) TransferDomainOut(accountID string, domainName string) (*DomainTransferOutResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/transfer_out", accountID, domainName))
|
|
||||||
transferResponse := &DomainTransferOutResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
transferResponse.HttpResponse = resp
|
|
||||||
return transferResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainRenewRequest represents the attributes you can pass to a renew API request.
|
|
||||||
// Some attributes are mandatory.
|
|
||||||
type DomainRenewRequest struct {
|
|
||||||
// The number of years
|
|
||||||
Period int `json:"period"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainRenewalResponse represents a response from an API method that results in a domain renewal.
|
|
||||||
type DomainRenewalResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Domain `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RenewDomain renews a domain name.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/#register
|
|
||||||
func (s *RegistrarService) RenewDomain(accountID string, domainName string, request *DomainRenewRequest) (*DomainRenewalResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/renewal", accountID, domainName))
|
|
||||||
renewalResponse := &DomainRenewalResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, request, renewalResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
renewalResponse.HttpResponse = resp
|
|
||||||
return renewalResponse, nil
|
|
||||||
}
|
|
@ -1,37 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// EnableDomainAutoRenewal enables auto-renewal for the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/auto-renewal/#enable
|
|
||||||
func (s *RegistrarService) EnableDomainAutoRenewal(accountID string, domainName string) (*DomainResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/auto_renewal", accountID, domainName))
|
|
||||||
domainResponse := &DomainResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.put(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainResponse.HttpResponse = resp
|
|
||||||
return domainResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableDomainAutoRenewal disables auto-renewal for the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/auto-renewal/#enable
|
|
||||||
func (s *RegistrarService) DisableDomainAutoRenewal(accountID string, domainName string) (*DomainResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/auto_renewal", accountID, domainName))
|
|
||||||
domainResponse := &DomainResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
domainResponse.HttpResponse = resp
|
|
||||||
return domainResponse, nil
|
|
||||||
}
|
|
@ -1,84 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Delegation represents a list of name servers that correspond to a domain delegation.
|
|
||||||
type Delegation []string
|
|
||||||
|
|
||||||
// DelegationResponse represents a response from an API method that returns a delegation struct.
|
|
||||||
type DelegationResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Delegation `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// VanityDelegationResponse represents a response for vanity name server enable and disable operations.
|
|
||||||
type VanityDelegationResponse struct {
|
|
||||||
Response
|
|
||||||
Data []VanityNameServer `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetDomainDelegation gets the current delegated name servers for the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/delegation/#get
|
|
||||||
func (s *RegistrarService) GetDomainDelegation(accountID string, domainName string) (*DelegationResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation", accountID, domainName))
|
|
||||||
delegationResponse := &DelegationResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, delegationResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
delegationResponse.HttpResponse = resp
|
|
||||||
return delegationResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeDomainDelegation updates the delegated name severs for the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/delegation/#get
|
|
||||||
func (s *RegistrarService) ChangeDomainDelegation(accountID string, domainName string, newDelegation *Delegation) (*DelegationResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation", accountID, domainName))
|
|
||||||
delegationResponse := &DelegationResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.put(path, newDelegation, delegationResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
delegationResponse.HttpResponse = resp
|
|
||||||
return delegationResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeDomainDelegationToVanity enables vanity name servers for the given domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/delegation/#delegateToVanity
|
|
||||||
func (s *RegistrarService) ChangeDomainDelegationToVanity(accountID string, domainName string, newDelegation *Delegation) (*VanityDelegationResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation/vanity", accountID, domainName))
|
|
||||||
delegationResponse := &VanityDelegationResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.put(path, newDelegation, delegationResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
delegationResponse.HttpResponse = resp
|
|
||||||
return delegationResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ChangeDomainDelegationFromVanity disables vanity name servers for the given domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/delegation/#dedelegateFromVanity
|
|
||||||
func (s *RegistrarService) ChangeDomainDelegationFromVanity(accountID string, domainName string) (*VanityDelegationResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/delegation/vanity", accountID, domainName))
|
|
||||||
delegationResponse := &VanityDelegationResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
delegationResponse.HttpResponse = resp
|
|
||||||
return delegationResponse, nil
|
|
||||||
}
|
|
@ -1,69 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WhoisPrivacy represents a whois privacy in DNSimple.
|
|
||||||
type WhoisPrivacy struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
DomainID int `json:"domain_id,omitempty"`
|
|
||||||
Enabled bool `json:"enabled,omitempty"`
|
|
||||||
ExpiresOn string `json:"expires_on,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// WhoisPrivacyResponse represents a response from an API method that returns a WhoisPrivacy struct.
|
|
||||||
type WhoisPrivacyResponse struct {
|
|
||||||
Response
|
|
||||||
Data *WhoisPrivacy `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetWhoisPrivacy gets the whois privacy for the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/whois-privacy/#get
|
|
||||||
func (s *RegistrarService) GetWhoisPrivacy(accountID string, domainName string) (*WhoisPrivacyResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/whois_privacy", accountID, domainName))
|
|
||||||
privacyResponse := &WhoisPrivacyResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, privacyResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
privacyResponse.HttpResponse = resp
|
|
||||||
return privacyResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableWhoisPrivacy enables the whois privacy for the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/whois-privacy/#enable
|
|
||||||
func (s *RegistrarService) EnableWhoisPrivacy(accountID string, domainName string) (*WhoisPrivacyResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/whois_privacy", accountID, domainName))
|
|
||||||
privacyResponse := &WhoisPrivacyResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.put(path, nil, privacyResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
privacyResponse.HttpResponse = resp
|
|
||||||
return privacyResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisablePrivacy disables the whois privacy for the domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/registrar/whois-privacy/#enable
|
|
||||||
func (s *RegistrarService) DisableWhoisPrivacy(accountID string, domainName string) (*WhoisPrivacyResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/registrar/domains/%v/whois_privacy", accountID, domainName))
|
|
||||||
privacyResponse := &WhoisPrivacyResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, privacyResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
privacyResponse.HttpResponse = resp
|
|
||||||
return privacyResponse, nil
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ServicesService handles communication with the service related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/services/
|
|
||||||
type ServicesService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceSetting represents a single group of settings for a DNSimple Service.
|
|
||||||
type ServiceSetting struct {
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
Label string `json:"label,omitempty"`
|
|
||||||
Append string `json:"append,omitempty"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
Example string `json:"example,omitempty"`
|
|
||||||
Password bool `json:"password,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// Service represents a Service in DNSimple.
|
|
||||||
type Service struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
ShortName string `json:"short_name,omitempty"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
SetupDescription string `json:"setup_description,omitempty"`
|
|
||||||
RequiresSetup bool `json:"requires_setup,omitempty"`
|
|
||||||
DefaultSubdomain string `json:"default_subdomain,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
Settings []ServiceSetting `json:"settings,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func servicePath(serviceID string) string {
|
|
||||||
if serviceID != "" {
|
|
||||||
return fmt.Sprintf("/services/%v", serviceID)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("/services")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServiceResponse represents a response from an API method that returns a Service struct.
|
|
||||||
type ServiceResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Service `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ServicesResponse represents a response from an API method that returns a collection of Service struct.
|
|
||||||
type ServicesResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Service `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListServices lists the one-click services available in DNSimple.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/services/#list
|
|
||||||
func (s *ServicesService) ListServices(options *ListOptions) (*ServicesResponse, error) {
|
|
||||||
path := versioned(servicePath(""))
|
|
||||||
servicesResponse := &ServicesResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, servicesResponse)
|
|
||||||
if err != nil {
|
|
||||||
return servicesResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
servicesResponse.HttpResponse = resp
|
|
||||||
return servicesResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetService fetches a one-click service.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/services/#get
|
|
||||||
func (s *ServicesService) GetService(serviceIdentifier string) (*ServiceResponse, error) {
|
|
||||||
path := versioned(servicePath(serviceIdentifier))
|
|
||||||
serviceResponse := &ServiceResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, serviceResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceResponse.HttpResponse = resp
|
|
||||||
return serviceResponse, nil
|
|
||||||
}
|
|
@ -1,70 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
func domainServicesPath(accountID string, domainID string, serviceIdentifier string) string {
|
|
||||||
if serviceIdentifier != "" {
|
|
||||||
return fmt.Sprintf("/%v/domains/%v/services/%v", accountID, domainID, serviceIdentifier)
|
|
||||||
}
|
|
||||||
return fmt.Sprintf("/%v/domains/%v/services", accountID, domainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DomainServiceSettings represents optional settings when applying a DNSimple one-click service to a domain.
|
|
||||||
type DomainServiceSettings struct {
|
|
||||||
Settings map[string]string `url:"settings,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// AppliedServices lists the applied one-click services for a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/services/domains/#applied
|
|
||||||
func (s *ServicesService) AppliedServices(accountID string, domainID string, options *ListOptions) (*ServicesResponse, error) {
|
|
||||||
path := versioned(domainServicesPath(accountID, domainID, ""))
|
|
||||||
servicesResponse := &ServicesResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, servicesResponse)
|
|
||||||
if err != nil {
|
|
||||||
return servicesResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
servicesResponse.HttpResponse = resp
|
|
||||||
return servicesResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ApplyService applies a one-click services to a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/services/domains/#apply
|
|
||||||
func (s *ServicesService) ApplyService(accountID string, serviceIdentifier string, domainID string, settings DomainServiceSettings) (*ServiceResponse, error) {
|
|
||||||
path := versioned(domainServicesPath(accountID, domainID, serviceIdentifier))
|
|
||||||
serviceResponse := &ServiceResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, settings, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceResponse.HttpResponse = resp
|
|
||||||
return serviceResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnapplyService unapplies a one-click services from a domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/services/domains/#unapply
|
|
||||||
func (s *ServicesService) UnapplyService(accountID string, serviceIdentifier string, domainID string) (*ServiceResponse, error) {
|
|
||||||
path := versioned(domainServicesPath(accountID, domainID, serviceIdentifier))
|
|
||||||
serviceResponse := &ServiceResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceResponse.HttpResponse = resp
|
|
||||||
return serviceResponse, nil
|
|
||||||
}
|
|
@ -1,129 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TemplatesService handles communication with the template related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/
|
|
||||||
type TemplatesService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Template represents a Template in DNSimple.
|
|
||||||
type Template struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
AccountID int `json:"account_id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
ShortName string `json:"short_name,omitempty"`
|
|
||||||
Description string `json:"description,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func templatePath(accountID string, templateIdentifier string) string {
|
|
||||||
if templateIdentifier != "" {
|
|
||||||
return fmt.Sprintf("/%v/templates/%v", accountID, templateIdentifier)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("/%v/templates", accountID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateResponse represents a response from an API method that returns a Template struct.
|
|
||||||
type TemplateResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Template `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplatesResponse represents a response from an API method that returns a collection of Template struct.
|
|
||||||
type TemplatesResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Template `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListTemplates list the templates for an account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/#list
|
|
||||||
func (s *TemplatesService) ListTemplates(accountID string, options *ListOptions) (*TemplatesResponse, error) {
|
|
||||||
path := versioned(templatePath(accountID, ""))
|
|
||||||
templatesResponse := &TemplatesResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, templatesResponse)
|
|
||||||
if err != nil {
|
|
||||||
return templatesResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templatesResponse.HttpResponse = resp
|
|
||||||
return templatesResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateTemplate creates a new template.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/#create
|
|
||||||
func (s *TemplatesService) CreateTemplate(accountID string, templateAttributes Template) (*TemplateResponse, error) {
|
|
||||||
path := versioned(templatePath(accountID, ""))
|
|
||||||
templateResponse := &TemplateResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, templateAttributes, templateResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateResponse.HttpResponse = resp
|
|
||||||
return templateResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTemplate fetches a template.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/#get
|
|
||||||
func (s *TemplatesService) GetTemplate(accountID string, templateIdentifier string) (*TemplateResponse, error) {
|
|
||||||
path := versioned(templatePath(accountID, templateIdentifier))
|
|
||||||
templateResponse := &TemplateResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, templateResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateResponse.HttpResponse = resp
|
|
||||||
return templateResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateTemplate updates a template.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/#update
|
|
||||||
func (s *TemplatesService) UpdateTemplate(accountID string, templateIdentifier string, templateAttributes Template) (*TemplateResponse, error) {
|
|
||||||
path := versioned(templatePath(accountID, templateIdentifier))
|
|
||||||
templateResponse := &TemplateResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.patch(path, templateAttributes, templateResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateResponse.HttpResponse = resp
|
|
||||||
return templateResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteTemplate deletes a template.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/#delete
|
|
||||||
func (s *TemplatesService) DeleteTemplate(accountID string, templateIdentifier string) (*TemplateResponse, error) {
|
|
||||||
path := versioned(templatePath(accountID, templateIdentifier))
|
|
||||||
templateResponse := &TemplateResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateResponse.HttpResponse = resp
|
|
||||||
return templateResponse, nil
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ApplyTemplate applies a template to the given domain.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/domains/#apply
|
|
||||||
func (s *TemplatesService) ApplyTemplate(accountID string, templateIdentifier string, domainID string) (*TemplateResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("%v/templates/%v", domainPath(accountID, domainID), templateIdentifier))
|
|
||||||
templateResponse := &TemplateResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateResponse.HttpResponse = resp
|
|
||||||
return templateResponse, nil
|
|
||||||
}
|
|
@ -1,107 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TemplateRecord represents a DNS record for a template in DNSimple.
|
|
||||||
type TemplateRecord struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
TemplateID int `json:"template_id,omitempty"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Content string `json:"content,omitempty"`
|
|
||||||
TTL int `json:"ttl,omitempty"`
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Priority int `json:"priority,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateRecordResponse represents a response from an API method that returns a TemplateRecord struct.
|
|
||||||
type TemplateRecordResponse struct {
|
|
||||||
Response
|
|
||||||
Data *TemplateRecord `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TemplateRecordsResponse represents a response from an API method that returns a collection of TemplateRecord struct.
|
|
||||||
type TemplateRecordsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []TemplateRecord `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func templateRecordPath(accountID string, templateIdentifier string, templateRecordID string) string {
|
|
||||||
if templateRecordID != "" {
|
|
||||||
return fmt.Sprintf("%v/records/%v", templatePath(accountID, templateIdentifier), templateRecordID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return templatePath(accountID, templateIdentifier) + "/records"
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListTemplateRecords list the templates for an account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/records/#list
|
|
||||||
func (s *TemplatesService) ListTemplateRecords(accountID string, templateIdentifier string, options *ListOptions) (*TemplateRecordsResponse, error) {
|
|
||||||
path := versioned(templateRecordPath(accountID, templateIdentifier, ""))
|
|
||||||
templateRecordsResponse := &TemplateRecordsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, templateRecordsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return templateRecordsResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateRecordsResponse.HttpResponse = resp
|
|
||||||
return templateRecordsResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateTemplateRecord creates a new template record.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/records/#create
|
|
||||||
func (s *TemplatesService) CreateTemplateRecord(accountID string, templateIdentifier string, templateRecordAttributes TemplateRecord) (*TemplateRecordResponse, error) {
|
|
||||||
path := versioned(templateRecordPath(accountID, templateIdentifier, ""))
|
|
||||||
templateRecordResponse := &TemplateRecordResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, templateRecordAttributes, templateRecordResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateRecordResponse.HttpResponse = resp
|
|
||||||
return templateRecordResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTemplateRecord fetches a template record.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/records/#get
|
|
||||||
func (s *TemplatesService) GetTemplateRecord(accountID string, templateIdentifier string, templateRecordID string) (*TemplateRecordResponse, error) {
|
|
||||||
path := versioned(templateRecordPath(accountID, templateIdentifier, templateRecordID))
|
|
||||||
templateRecordResponse := &TemplateRecordResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, templateRecordResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateRecordResponse.HttpResponse = resp
|
|
||||||
return templateRecordResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteTemplateRecord deletes a template record.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/templates/records/#delete
|
|
||||||
func (s *TemplatesService) DeleteTemplateRecord(accountID string, templateIdentifier string, templateRecordID string) (*TemplateRecordResponse, error) {
|
|
||||||
path := versioned(templateRecordPath(accountID, templateIdentifier, templateRecordID))
|
|
||||||
templateRecordResponse := &TemplateRecordResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
templateRecordResponse.HttpResponse = resp
|
|
||||||
return templateRecordResponse, nil
|
|
||||||
}
|
|
@ -1,117 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// TldsService handles communication with the Tld related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/tlds/
|
|
||||||
type TldsService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tld represents a TLD in DNSimple.
|
|
||||||
type Tld struct {
|
|
||||||
Tld string `json:"tld"`
|
|
||||||
TldType int `json:"tld_type"`
|
|
||||||
WhoisPrivacy bool `json:"whois_privacy"`
|
|
||||||
AutoRenewOnly bool `json:"auto_renew_only"`
|
|
||||||
MinimumRegistration int `json:"minimum_registration"`
|
|
||||||
RegistrationEnabled bool `json:"registration_enabled"`
|
|
||||||
RenewalEnabled bool `json:"renewal_enabled"`
|
|
||||||
TransferEnabled bool `json:"transfer_enabled"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TldExtendedAttribute represents an extended attributes supported or required
|
|
||||||
// by a specific TLD.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/tlds/
|
|
||||||
type TldExtendedAttribute struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Required bool `json:"required"`
|
|
||||||
Options []TldExtendedAttributeOption `json:"options"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TldExtendedAttributeOption represents a single option you can assign to an extended attributes.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/tlds/
|
|
||||||
type TldExtendedAttributeOption struct {
|
|
||||||
Title string `json:"title"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TldResponse represents a response from an API method that returns a Tld struct.
|
|
||||||
type TldResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Tld `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TldsResponse represents a response from an API method that returns a collection of Tld struct.
|
|
||||||
type TldsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Tld `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// TldExtendedAttributesResponse represents a response from an API method that returns
|
|
||||||
// a collection of Tld extended attributes.
|
|
||||||
type TldExtendedAttributesResponse struct {
|
|
||||||
Response
|
|
||||||
Data []TldExtendedAttribute `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListTlds lists the supported TLDs.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/tlds/#list
|
|
||||||
func (s *TldsService) ListTlds(options *ListOptions) (*TldsResponse, error) {
|
|
||||||
path := versioned("/tlds")
|
|
||||||
tldsResponse := &TldsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, tldsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return tldsResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tldsResponse.HttpResponse = resp
|
|
||||||
return tldsResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTld fetches a TLD.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/tlds/#get
|
|
||||||
func (s *TldsService) GetTld(tld string) (*TldResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/tlds/%s", tld))
|
|
||||||
tldResponse := &TldResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, tldResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tldResponse.HttpResponse = resp
|
|
||||||
return tldResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetTld fetches the extended attributes of a TLD.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/tlds/#get
|
|
||||||
func (s *TldsService) GetTldExtendedAttributes(tld string) (*TldExtendedAttributesResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/tlds/%s/extended_attributes", tld))
|
|
||||||
tldResponse := &TldExtendedAttributesResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, tldResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
tldResponse.HttpResponse = resp
|
|
||||||
return tldResponse, nil
|
|
||||||
}
|
|
@ -1,7 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
// User represents a DNSimple user.
|
|
||||||
type User struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
Email string `json:"email,omitempty"`
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VanityNameServersService handles communication with Vanity Name Servers
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/vanity/
|
|
||||||
type VanityNameServersService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// VanityNameServer represents data for a single vanity name server
|
|
||||||
type VanityNameServer struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
IPv4 string `json:"ipv4,omitempty"`
|
|
||||||
IPv6 string `json:"ipv6,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// VanityNameServerResponse represents a response for vanity name server enable and disable operations.
|
|
||||||
type VanityNameServerResponse struct {
|
|
||||||
Response
|
|
||||||
Data []VanityNameServer `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func vanityNameServerPath(accountID string, domainID string) string {
|
|
||||||
return fmt.Sprintf("/%v/vanity/%v", accountID, domainID)
|
|
||||||
}
|
|
||||||
|
|
||||||
// EnableVanityNameServers Vanity Name Servers for the given domain
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/vanity/#enable
|
|
||||||
func (s *VanityNameServersService) EnableVanityNameServers(accountID string, domainID string) (*VanityNameServerResponse, error) {
|
|
||||||
path := versioned(vanityNameServerPath(accountID, domainID))
|
|
||||||
vanityNameServerResponse := &VanityNameServerResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.put(path, nil, vanityNameServerResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
vanityNameServerResponse.HttpResponse = resp
|
|
||||||
return vanityNameServerResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DisableVanityNameServers Vanity Name Servers for the given domain
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/vanity/#disable
|
|
||||||
func (s *VanityNameServersService) DisableVanityNameServers(accountID string, domainID string) (*VanityNameServerResponse, error) {
|
|
||||||
path := versioned(vanityNameServerPath(accountID, domainID))
|
|
||||||
vanityNameServerResponse := &VanityNameServerResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
vanityNameServerResponse.HttpResponse = resp
|
|
||||||
return vanityNameServerResponse, nil
|
|
||||||
}
|
|
@ -1,104 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WebhooksService handles communication with the webhook related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/webhooks
|
|
||||||
type WebhooksService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Webhook represents a DNSimple webhook.
|
|
||||||
type Webhook struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
URL string `json:"url,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebhookResponse represents a response from an API method that returns a Webhook struct.
|
|
||||||
type WebhookResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Webhook `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// WebhookResponse represents a response from an API method that returns a collection of Webhook struct.
|
|
||||||
type WebhooksResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Webhook `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// webhookPath generates the resource path for given webhook.
|
|
||||||
func webhookPath(accountID string, webhookID int) (path string) {
|
|
||||||
path = fmt.Sprintf("/%v/webhooks", accountID)
|
|
||||||
if webhookID != 0 {
|
|
||||||
path = fmt.Sprintf("%v/%v", path, webhookID)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListWebhooks lists the webhooks for an account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/webhooks#list
|
|
||||||
func (s *WebhooksService) ListWebhooks(accountID string, _ *ListOptions) (*WebhooksResponse, error) {
|
|
||||||
path := versioned(webhookPath(accountID, 0))
|
|
||||||
webhooksResponse := &WebhooksResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, webhooksResponse)
|
|
||||||
if err != nil {
|
|
||||||
return webhooksResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
webhooksResponse.HttpResponse = resp
|
|
||||||
return webhooksResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateWebhook creates a new webhook.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/webhooks#create
|
|
||||||
func (s *WebhooksService) CreateWebhook(accountID string, webhookAttributes Webhook) (*WebhookResponse, error) {
|
|
||||||
path := versioned(webhookPath(accountID, 0))
|
|
||||||
webhookResponse := &WebhookResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, webhookAttributes, webhookResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
webhookResponse.HttpResponse = resp
|
|
||||||
return webhookResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetWebhook fetches a webhook.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/webhooks#get
|
|
||||||
func (s *WebhooksService) GetWebhook(accountID string, webhookID int) (*WebhookResponse, error) {
|
|
||||||
path := versioned(webhookPath(accountID, webhookID))
|
|
||||||
webhookResponse := &WebhookResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, webhookResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
webhookResponse.HttpResponse = resp
|
|
||||||
return webhookResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteWebhook PERMANENTLY deletes a webhook from the account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/webhooks#delete
|
|
||||||
func (s *WebhooksService) DeleteWebhook(accountID string, webhookID int) (*WebhookResponse, error) {
|
|
||||||
path := versioned(webhookPath(accountID, webhookID))
|
|
||||||
webhookResponse := &WebhookResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
webhookResponse.HttpResponse = resp
|
|
||||||
return webhookResponse, nil
|
|
||||||
}
|
|
@ -1,108 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ZonesService handles communication with the zone related
|
|
||||||
// methods of the DNSimple API.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/
|
|
||||||
type ZonesService struct {
|
|
||||||
client *Client
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zone represents a Zone in DNSimple.
|
|
||||||
type Zone struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
AccountID int `json:"account_id,omitempty"`
|
|
||||||
Name string `json:"name,omitempty"`
|
|
||||||
Reverse bool `json:"reverse,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneFile represents a Zone File in DNSimple.
|
|
||||||
type ZoneFile struct {
|
|
||||||
Zone string `json:"zone,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneListOptions specifies the optional parameters you can provide
|
|
||||||
// to customize the ZonesService.ListZones method.
|
|
||||||
type ZoneListOptions struct {
|
|
||||||
// Select domains where the name contains given string.
|
|
||||||
NameLike string `url:"name_like,omitempty"`
|
|
||||||
|
|
||||||
ListOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneResponse represents a response from an API method that returns a Zone struct.
|
|
||||||
type ZoneResponse struct {
|
|
||||||
Response
|
|
||||||
Data *Zone `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZonesResponse represents a response from an API method that returns a collection of Zone struct.
|
|
||||||
type ZonesResponse struct {
|
|
||||||
Response
|
|
||||||
Data []Zone `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneFileResponse represents a response from an API method that returns a ZoneFile struct.
|
|
||||||
type ZoneFileResponse struct {
|
|
||||||
Response
|
|
||||||
Data *ZoneFile `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListZones the zones for an account.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#list
|
|
||||||
func (s *ZonesService) ListZones(accountID string, options *ZoneListOptions) (*ZonesResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/zones", accountID))
|
|
||||||
zonesResponse := &ZonesResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, zonesResponse)
|
|
||||||
if err != nil {
|
|
||||||
return zonesResponse, err
|
|
||||||
}
|
|
||||||
|
|
||||||
zonesResponse.HttpResponse = resp
|
|
||||||
return zonesResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetZone fetches a zone.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#get
|
|
||||||
func (s *ZonesService) GetZone(accountID string, zoneName string) (*ZoneResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/zones/%v", accountID, zoneName))
|
|
||||||
zoneResponse := &ZoneResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, zoneResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneResponse.HttpResponse = resp
|
|
||||||
return zoneResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetZoneFile fetches a zone file.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#get-file
|
|
||||||
func (s *ZonesService) GetZoneFile(accountID string, zoneName string) (*ZoneFileResponse, error) {
|
|
||||||
path := versioned(fmt.Sprintf("/%v/zones/%v/file", accountID, zoneName))
|
|
||||||
zoneFileResponse := &ZoneFileResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, zoneFileResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
zoneFileResponse.HttpResponse = resp
|
|
||||||
return zoneFileResponse, nil
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
package dnsimple
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ZoneRecord represents a DNS record in DNSimple.
|
|
||||||
type ZoneRecord struct {
|
|
||||||
ID int `json:"id,omitempty"`
|
|
||||||
ZoneID string `json:"zone_id,omitempty"`
|
|
||||||
ParentID int `json:"parent_id,omitempty"`
|
|
||||||
Type string `json:"type,omitempty"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Content string `json:"content,omitempty"`
|
|
||||||
TTL int `json:"ttl,omitempty"`
|
|
||||||
Priority int `json:"priority,omitempty"`
|
|
||||||
SystemRecord bool `json:"system_record,omitempty"`
|
|
||||||
Regions []string `json:"regions,omitempty"`
|
|
||||||
CreatedAt string `json:"created_at,omitempty"`
|
|
||||||
UpdatedAt string `json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneRecordListOptions specifies the optional parameters you can provide
|
|
||||||
// to customize the ZonesService.ListZoneRecords method.
|
|
||||||
type ZoneRecordListOptions struct {
|
|
||||||
// Select records where the name matches given string.
|
|
||||||
Name string `url:"name,omitempty"`
|
|
||||||
|
|
||||||
// Select records where the name contains given string.
|
|
||||||
NameLike string `url:"name_like,omitempty"`
|
|
||||||
|
|
||||||
// Select records of given type.
|
|
||||||
// Eg. TXT, A, NS.
|
|
||||||
Type string `url:"record_type,omitempty"`
|
|
||||||
|
|
||||||
ListOptions
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneRecordResponse represents a response from an API method that returns a ZoneRecord struct.
|
|
||||||
type ZoneRecordResponse struct {
|
|
||||||
Response
|
|
||||||
Data *ZoneRecord `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// ZoneRecordsResponse represents a response from an API method that returns a collection of ZoneRecord struct.
|
|
||||||
type ZoneRecordsResponse struct {
|
|
||||||
Response
|
|
||||||
Data []ZoneRecord `json:"data"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func zoneRecordPath(accountID string, zoneID string, recordID int) string {
|
|
||||||
path := fmt.Sprintf("/%v/zones/%v/records", accountID, zoneID)
|
|
||||||
|
|
||||||
if recordID != 0 {
|
|
||||||
path += fmt.Sprintf("/%d", recordID)
|
|
||||||
}
|
|
||||||
|
|
||||||
return path
|
|
||||||
}
|
|
||||||
|
|
||||||
// ListRecords lists the zone records for a zone.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#list
|
|
||||||
func (s *ZonesService) ListRecords(accountID string, zoneID string, options *ZoneRecordListOptions) (*ZoneRecordsResponse, error) {
|
|
||||||
path := versioned(zoneRecordPath(accountID, zoneID, 0))
|
|
||||||
recordsResponse := &ZoneRecordsResponse{}
|
|
||||||
|
|
||||||
path, err := addURLQueryOptions(path, options)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, recordsResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
recordsResponse.HttpResponse = resp
|
|
||||||
return recordsResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateRecord creates a zone record.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#create
|
|
||||||
func (s *ZonesService) CreateRecord(accountID string, zoneID string, recordAttributes ZoneRecord) (*ZoneRecordResponse, error) {
|
|
||||||
path := versioned(zoneRecordPath(accountID, zoneID, 0))
|
|
||||||
recordResponse := &ZoneRecordResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.post(path, recordAttributes, recordResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
recordResponse.HttpResponse = resp
|
|
||||||
return recordResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetRecord fetches a zone record.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#get
|
|
||||||
func (s *ZonesService) GetRecord(accountID string, zoneID string, recordID int) (*ZoneRecordResponse, error) {
|
|
||||||
path := versioned(zoneRecordPath(accountID, zoneID, recordID))
|
|
||||||
recordResponse := &ZoneRecordResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.get(path, recordResponse)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
recordResponse.HttpResponse = resp
|
|
||||||
return recordResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateRecord updates a zone record.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#update
|
|
||||||
func (s *ZonesService) UpdateRecord(accountID string, zoneID string, recordID int, recordAttributes ZoneRecord) (*ZoneRecordResponse, error) {
|
|
||||||
path := versioned(zoneRecordPath(accountID, zoneID, recordID))
|
|
||||||
recordResponse := &ZoneRecordResponse{}
|
|
||||||
resp, err := s.client.patch(path, recordAttributes, recordResponse)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
recordResponse.HttpResponse = resp
|
|
||||||
return recordResponse, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteRecord PERMANENTLY deletes a zone record from the zone.
|
|
||||||
//
|
|
||||||
// See https://developer.dnsimple.com/v2/zones/#delete
|
|
||||||
func (s *ZonesService) DeleteRecord(accountID string, zoneID string, recordID int) (*ZoneRecordResponse, error) {
|
|
||||||
path := versioned(zoneRecordPath(accountID, zoneID, recordID))
|
|
||||||
recordResponse := &ZoneRecordResponse{}
|
|
||||||
|
|
||||||
resp, err := s.client.delete(path, nil, nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
recordResponse.HttpResponse = resp
|
|
||||||
return recordResponse, nil
|
|
||||||
}
|
|
@ -1,27 +0,0 @@
|
|||||||
Copyright (c) 2013 Google. All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following disclaimer
|
|
||||||
in the documentation and/or other materials provided with the
|
|
||||||
distribution.
|
|
||||||
* Neither the name of Google Inc. nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived from
|
|
||||||
this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,320 +0,0 @@
|
|||||||
// Copyright 2013 The Go Authors. All rights reserved.
|
|
||||||
// Use of this source code is governed by a BSD-style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
// Package query implements encoding of structs into URL query parameters.
|
|
||||||
//
|
|
||||||
// As a simple example:
|
|
||||||
//
|
|
||||||
// type Options struct {
|
|
||||||
// Query string `url:"q"`
|
|
||||||
// ShowAll bool `url:"all"`
|
|
||||||
// Page int `url:"page"`
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// opt := Options{ "foo", true, 2 }
|
|
||||||
// v, _ := query.Values(opt)
|
|
||||||
// fmt.Print(v.Encode()) // will output: "q=foo&all=true&page=2"
|
|
||||||
//
|
|
||||||
// The exact mapping between Go values and url.Values is described in the
|
|
||||||
// documentation for the Values() function.
|
|
||||||
package query
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"fmt"
|
|
||||||
"net/url"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var timeType = reflect.TypeOf(time.Time{})
|
|
||||||
|
|
||||||
var encoderType = reflect.TypeOf(new(Encoder)).Elem()
|
|
||||||
|
|
||||||
// Encoder is an interface implemented by any type that wishes to encode
|
|
||||||
// itself into URL values in a non-standard way.
|
|
||||||
type Encoder interface {
|
|
||||||
EncodeValues(key string, v *url.Values) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// Values returns the url.Values encoding of v.
|
|
||||||
//
|
|
||||||
// Values expects to be passed a struct, and traverses it recursively using the
|
|
||||||
// following encoding rules.
|
|
||||||
//
|
|
||||||
// Each exported struct field is encoded as a URL parameter unless
|
|
||||||
//
|
|
||||||
// - the field's tag is "-", or
|
|
||||||
// - the field is empty and its tag specifies the "omitempty" option
|
|
||||||
//
|
|
||||||
// The empty values are false, 0, any nil pointer or interface value, any array
|
|
||||||
// slice, map, or string of length zero, and any time.Time that returns true
|
|
||||||
// for IsZero().
|
|
||||||
//
|
|
||||||
// The URL parameter name defaults to the struct field name but can be
|
|
||||||
// specified in the struct field's tag value. The "url" key in the struct
|
|
||||||
// field's tag value is the key name, followed by an optional comma and
|
|
||||||
// options. For example:
|
|
||||||
//
|
|
||||||
// // Field is ignored by this package.
|
|
||||||
// Field int `url:"-"`
|
|
||||||
//
|
|
||||||
// // Field appears as URL parameter "myName".
|
|
||||||
// Field int `url:"myName"`
|
|
||||||
//
|
|
||||||
// // Field appears as URL parameter "myName" and the field is omitted if
|
|
||||||
// // its value is empty
|
|
||||||
// Field int `url:"myName,omitempty"`
|
|
||||||
//
|
|
||||||
// // Field appears as URL parameter "Field" (the default), but the field
|
|
||||||
// // is skipped if empty. Note the leading comma.
|
|
||||||
// Field int `url:",omitempty"`
|
|
||||||
//
|
|
||||||
// For encoding individual field values, the following type-dependent rules
|
|
||||||
// apply:
|
|
||||||
//
|
|
||||||
// Boolean values default to encoding as the strings "true" or "false".
|
|
||||||
// Including the "int" option signals that the field should be encoded as the
|
|
||||||
// strings "1" or "0".
|
|
||||||
//
|
|
||||||
// time.Time values default to encoding as RFC3339 timestamps. Including the
|
|
||||||
// "unix" option signals that the field should be encoded as a Unix time (see
|
|
||||||
// time.Unix())
|
|
||||||
//
|
|
||||||
// Slice and Array values default to encoding as multiple URL values of the
|
|
||||||
// same name. Including the "comma" option signals that the field should be
|
|
||||||
// encoded as a single comma-delimited value. Including the "space" option
|
|
||||||
// similarly encodes the value as a single space-delimited string. Including
|
|
||||||
// the "semicolon" option will encode the value as a semicolon-delimited string.
|
|
||||||
// Including the "brackets" option signals that the multiple URL values should
|
|
||||||
// have "[]" appended to the value name. "numbered" will append a number to
|
|
||||||
// the end of each incidence of the value name, example:
|
|
||||||
// name0=value0&name1=value1, etc.
|
|
||||||
//
|
|
||||||
// Anonymous struct fields are usually encoded as if their inner exported
|
|
||||||
// fields were fields in the outer struct, subject to the standard Go
|
|
||||||
// visibility rules. An anonymous struct field with a name given in its URL
|
|
||||||
// tag is treated as having that name, rather than being anonymous.
|
|
||||||
//
|
|
||||||
// Non-nil pointer values are encoded as the value pointed to.
|
|
||||||
//
|
|
||||||
// Nested structs are encoded including parent fields in value names for
|
|
||||||
// scoping. e.g:
|
|
||||||
//
|
|
||||||
// "user[name]=acme&user[addr][postcode]=1234&user[addr][city]=SFO"
|
|
||||||
//
|
|
||||||
// All other values are encoded using their default string representation.
|
|
||||||
//
|
|
||||||
// Multiple fields that encode to the same URL parameter name will be included
|
|
||||||
// as multiple URL values of the same name.
|
|
||||||
func Values(v interface{}) (url.Values, error) {
|
|
||||||
values := make(url.Values)
|
|
||||||
val := reflect.ValueOf(v)
|
|
||||||
for val.Kind() == reflect.Ptr {
|
|
||||||
if val.IsNil() {
|
|
||||||
return values, nil
|
|
||||||
}
|
|
||||||
val = val.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
if v == nil {
|
|
||||||
return values, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if val.Kind() != reflect.Struct {
|
|
||||||
return nil, fmt.Errorf("query: Values() expects struct input. Got %v", val.Kind())
|
|
||||||
}
|
|
||||||
|
|
||||||
err := reflectValue(values, val, "")
|
|
||||||
return values, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// reflectValue populates the values parameter from the struct fields in val.
|
|
||||||
// Embedded structs are followed recursively (using the rules defined in the
|
|
||||||
// Values function documentation) breadth-first.
|
|
||||||
func reflectValue(values url.Values, val reflect.Value, scope string) error {
|
|
||||||
var embedded []reflect.Value
|
|
||||||
|
|
||||||
typ := val.Type()
|
|
||||||
for i := 0; i < typ.NumField(); i++ {
|
|
||||||
sf := typ.Field(i)
|
|
||||||
if sf.PkgPath != "" && !sf.Anonymous { // unexported
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
sv := val.Field(i)
|
|
||||||
tag := sf.Tag.Get("url")
|
|
||||||
if tag == "-" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name, opts := parseTag(tag)
|
|
||||||
if name == "" {
|
|
||||||
if sf.Anonymous && sv.Kind() == reflect.Struct {
|
|
||||||
// save embedded struct for later processing
|
|
||||||
embedded = append(embedded, sv)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
name = sf.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
if scope != "" {
|
|
||||||
name = scope + "[" + name + "]"
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.Contains("omitempty") && isEmptyValue(sv) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if sv.Type().Implements(encoderType) {
|
|
||||||
if !reflect.Indirect(sv).IsValid() {
|
|
||||||
sv = reflect.New(sv.Type().Elem())
|
|
||||||
}
|
|
||||||
|
|
||||||
m := sv.Interface().(Encoder)
|
|
||||||
if err := m.EncodeValues(name, &values); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if sv.Kind() == reflect.Slice || sv.Kind() == reflect.Array {
|
|
||||||
var del byte
|
|
||||||
if opts.Contains("comma") {
|
|
||||||
del = ','
|
|
||||||
} else if opts.Contains("space") {
|
|
||||||
del = ' '
|
|
||||||
} else if opts.Contains("semicolon") {
|
|
||||||
del = ';'
|
|
||||||
} else if opts.Contains("brackets") {
|
|
||||||
name = name + "[]"
|
|
||||||
}
|
|
||||||
|
|
||||||
if del != 0 {
|
|
||||||
s := new(bytes.Buffer)
|
|
||||||
first := true
|
|
||||||
for i := 0; i < sv.Len(); i++ {
|
|
||||||
if first {
|
|
||||||
first = false
|
|
||||||
} else {
|
|
||||||
s.WriteByte(del)
|
|
||||||
}
|
|
||||||
s.WriteString(valueString(sv.Index(i), opts))
|
|
||||||
}
|
|
||||||
values.Add(name, s.String())
|
|
||||||
} else {
|
|
||||||
for i := 0; i < sv.Len(); i++ {
|
|
||||||
k := name
|
|
||||||
if opts.Contains("numbered") {
|
|
||||||
k = fmt.Sprintf("%s%d", name, i)
|
|
||||||
}
|
|
||||||
values.Add(k, valueString(sv.Index(i), opts))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if sv.Type() == timeType {
|
|
||||||
values.Add(name, valueString(sv, opts))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
for sv.Kind() == reflect.Ptr {
|
|
||||||
if sv.IsNil() {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
sv = sv.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
if sv.Kind() == reflect.Struct {
|
|
||||||
reflectValue(values, sv, name)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
values.Add(name, valueString(sv, opts))
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, f := range embedded {
|
|
||||||
if err := reflectValue(values, f, scope); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// valueString returns the string representation of a value.
|
|
||||||
func valueString(v reflect.Value, opts tagOptions) string {
|
|
||||||
for v.Kind() == reflect.Ptr {
|
|
||||||
if v.IsNil() {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
v = v.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Kind() == reflect.Bool && opts.Contains("int") {
|
|
||||||
if v.Bool() {
|
|
||||||
return "1"
|
|
||||||
}
|
|
||||||
return "0"
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Type() == timeType {
|
|
||||||
t := v.Interface().(time.Time)
|
|
||||||
if opts.Contains("unix") {
|
|
||||||
return strconv.FormatInt(t.Unix(), 10)
|
|
||||||
}
|
|
||||||
return t.Format(time.RFC3339)
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprint(v.Interface())
|
|
||||||
}
|
|
||||||
|
|
||||||
// isEmptyValue checks if a value should be considered empty for the purposes
|
|
||||||
// of omitting fields with the "omitempty" option.
|
|
||||||
func isEmptyValue(v reflect.Value) bool {
|
|
||||||
switch v.Kind() {
|
|
||||||
case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
|
|
||||||
return v.Len() == 0
|
|
||||||
case reflect.Bool:
|
|
||||||
return !v.Bool()
|
|
||||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
||||||
return v.Int() == 0
|
|
||||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
|
|
||||||
return v.Uint() == 0
|
|
||||||
case reflect.Float32, reflect.Float64:
|
|
||||||
return v.Float() == 0
|
|
||||||
case reflect.Interface, reflect.Ptr:
|
|
||||||
return v.IsNil()
|
|
||||||
}
|
|
||||||
|
|
||||||
if v.Type() == timeType {
|
|
||||||
return v.Interface().(time.Time).IsZero()
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// tagOptions is the string following a comma in a struct field's "url" tag, or
|
|
||||||
// the empty string. It does not include the leading comma.
|
|
||||||
type tagOptions []string
|
|
||||||
|
|
||||||
// parseTag splits a struct field's url tag into its name and comma-separated
|
|
||||||
// options.
|
|
||||||
func parseTag(tag string) (string, tagOptions) {
|
|
||||||
s := strings.Split(tag, ",")
|
|
||||||
return s[0], s[1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contains checks whether the tagOptions contains the specified option.
|
|
||||||
func (o tagOptions) Contains(option string) bool {
|
|
||||||
for _, s := range o {
|
|
||||||
if s == option {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
Copyright (c) 2015, Dave Cheney <dave@cheney.net>
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright notice, this
|
|
||||||
list of conditions and the following disclaimer.
|
|
||||||
|
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
this list of conditions and the following disclaimer in the documentation
|
|
||||||
and/or other materials provided with the distribution.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
||||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
||||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
||||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
||||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
||||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
||||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
||||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
@ -1,52 +0,0 @@
|
|||||||
# errors [![Travis-CI](https://travis-ci.org/pkg/errors.svg)](https://travis-ci.org/pkg/errors) [![AppVeyor](https://ci.appveyor.com/api/projects/status/b98mptawhudj53ep/branch/master?svg=true)](https://ci.appveyor.com/project/davecheney/errors/branch/master) [![GoDoc](https://godoc.org/github.com/pkg/errors?status.svg)](http://godoc.org/github.com/pkg/errors) [![Report card](https://goreportcard.com/badge/github.com/pkg/errors)](https://goreportcard.com/report/github.com/pkg/errors)
|
|
||||||
|
|
||||||
Package errors provides simple error handling primitives.
|
|
||||||
|
|
||||||
`go get github.com/pkg/errors`
|
|
||||||
|
|
||||||
The traditional error handling idiom in Go is roughly akin to
|
|
||||||
```go
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
```
|
|
||||||
which applied recursively up the call stack results in error reports without context or debugging information. The errors package allows programmers to add context to the failure path in their code in a way that does not destroy the original value of the error.
|
|
||||||
|
|
||||||
## Adding context to an error
|
|
||||||
|
|
||||||
The errors.Wrap function returns a new error that adds context to the original error. For example
|
|
||||||
```go
|
|
||||||
_, err := ioutil.ReadAll(r)
|
|
||||||
if err != nil {
|
|
||||||
return errors.Wrap(err, "read failed")
|
|
||||||
}
|
|
||||||
```
|
|
||||||
## Retrieving the cause of an error
|
|
||||||
|
|
||||||
Using `errors.Wrap` constructs a stack of errors, adding context to the preceding error. Depending on the nature of the error it may be necessary to reverse the operation of errors.Wrap to retrieve the original error for inspection. Any error value which implements this interface can be inspected by `errors.Cause`.
|
|
||||||
```go
|
|
||||||
type causer interface {
|
|
||||||
Cause() error
|
|
||||||
}
|
|
||||||
```
|
|
||||||
`errors.Cause` will recursively retrieve the topmost error which does not implement `causer`, which is assumed to be the original cause. For example:
|
|
||||||
```go
|
|
||||||
switch err := errors.Cause(err).(type) {
|
|
||||||
case *MyError:
|
|
||||||
// handle specifically
|
|
||||||
default:
|
|
||||||
// unknown error
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
[Read the package documentation for more information](https://godoc.org/github.com/pkg/errors).
|
|
||||||
|
|
||||||
## Contributing
|
|
||||||
|
|
||||||
We welcome pull requests, bug fixes and issue reports. With that said, the bar for adding new symbols to this package is intentionally set high.
|
|
||||||
|
|
||||||
Before proposing a change, please discuss your change by raising an issue.
|
|
||||||
|
|
||||||
## Licence
|
|
||||||
|
|
||||||
BSD-2-Clause
|
|
@ -1,32 +0,0 @@
|
|||||||
version: build-{build}.{branch}
|
|
||||||
|
|
||||||
clone_folder: C:\gopath\src\github.com\pkg\errors
|
|
||||||
shallow_clone: true # for startup speed
|
|
||||||
|
|
||||||
environment:
|
|
||||||
GOPATH: C:\gopath
|
|
||||||
|
|
||||||
platform:
|
|
||||||
- x64
|
|
||||||
|
|
||||||
# http://www.appveyor.com/docs/installed-software
|
|
||||||
install:
|
|
||||||
# some helpful output for debugging builds
|
|
||||||
- go version
|
|
||||||
- go env
|
|
||||||
# pre-installed MinGW at C:\MinGW is 32bit only
|
|
||||||
# but MSYS2 at C:\msys64 has mingw64
|
|
||||||
- set PATH=C:\msys64\mingw64\bin;%PATH%
|
|
||||||
- gcc --version
|
|
||||||
- g++ --version
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- go install -v ./...
|
|
||||||
|
|
||||||
test_script:
|
|
||||||
- set PATH=C:\gopath\bin;%PATH%
|
|
||||||
- go test -v ./...
|
|
||||||
|
|
||||||
#artifacts:
|
|
||||||
# - path: '%GOPATH%\bin\*.exe'
|
|
||||||
deploy: off
|
|
@ -1,269 +0,0 @@
|
|||||||
// Package errors provides simple error handling primitives.
|
|
||||||
//
|
|
||||||
// The traditional error handling idiom in Go is roughly akin to
|
|
||||||
//
|
|
||||||
// if err != nil {
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// which applied recursively up the call stack results in error reports
|
|
||||||
// without context or debugging information. The errors package allows
|
|
||||||
// programmers to add context to the failure path in their code in a way
|
|
||||||
// that does not destroy the original value of the error.
|
|
||||||
//
|
|
||||||
// Adding context to an error
|
|
||||||
//
|
|
||||||
// The errors.Wrap function returns a new error that adds context to the
|
|
||||||
// original error by recording a stack trace at the point Wrap is called,
|
|
||||||
// and the supplied message. For example
|
|
||||||
//
|
|
||||||
// _, err := ioutil.ReadAll(r)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.Wrap(err, "read failed")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// If additional control is required the errors.WithStack and errors.WithMessage
|
|
||||||
// functions destructure errors.Wrap into its component operations of annotating
|
|
||||||
// an error with a stack trace and an a message, respectively.
|
|
||||||
//
|
|
||||||
// Retrieving the cause of an error
|
|
||||||
//
|
|
||||||
// Using errors.Wrap constructs a stack of errors, adding context to the
|
|
||||||
// preceding error. Depending on the nature of the error it may be necessary
|
|
||||||
// to reverse the operation of errors.Wrap to retrieve the original error
|
|
||||||
// for inspection. Any error value which implements this interface
|
|
||||||
//
|
|
||||||
// type causer interface {
|
|
||||||
// Cause() error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// can be inspected by errors.Cause. errors.Cause will recursively retrieve
|
|
||||||
// the topmost error which does not implement causer, which is assumed to be
|
|
||||||
// the original cause. For example:
|
|
||||||
//
|
|
||||||
// switch err := errors.Cause(err).(type) {
|
|
||||||
// case *MyError:
|
|
||||||
// // handle specifically
|
|
||||||
// default:
|
|
||||||
// // unknown error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// causer interface is not exported by this package, but is considered a part
|
|
||||||
// of stable public API.
|
|
||||||
//
|
|
||||||
// Formatted printing of errors
|
|
||||||
//
|
|
||||||
// All error values returned from this package implement fmt.Formatter and can
|
|
||||||
// be formatted by the fmt package. The following verbs are supported
|
|
||||||
//
|
|
||||||
// %s print the error. If the error has a Cause it will be
|
|
||||||
// printed recursively
|
|
||||||
// %v see %s
|
|
||||||
// %+v extended format. Each Frame of the error's StackTrace will
|
|
||||||
// be printed in detail.
|
|
||||||
//
|
|
||||||
// Retrieving the stack trace of an error or wrapper
|
|
||||||
//
|
|
||||||
// New, Errorf, Wrap, and Wrapf record a stack trace at the point they are
|
|
||||||
// invoked. This information can be retrieved with the following interface.
|
|
||||||
//
|
|
||||||
// type stackTracer interface {
|
|
||||||
// StackTrace() errors.StackTrace
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Where errors.StackTrace is defined as
|
|
||||||
//
|
|
||||||
// type StackTrace []Frame
|
|
||||||
//
|
|
||||||
// The Frame type represents a call site in the stack trace. Frame supports
|
|
||||||
// the fmt.Formatter interface that can be used for printing information about
|
|
||||||
// the stack trace of this error. For example:
|
|
||||||
//
|
|
||||||
// if err, ok := err.(stackTracer); ok {
|
|
||||||
// for _, f := range err.StackTrace() {
|
|
||||||
// fmt.Printf("%+s:%d", f)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// stackTracer interface is not exported by this package, but is considered a part
|
|
||||||
// of stable public API.
|
|
||||||
//
|
|
||||||
// See the documentation for Frame.Format for more details.
|
|
||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
)
|
|
||||||
|
|
||||||
// New returns an error with the supplied message.
|
|
||||||
// New also records the stack trace at the point it was called.
|
|
||||||
func New(message string) error {
|
|
||||||
return &fundamental{
|
|
||||||
msg: message,
|
|
||||||
stack: callers(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Errorf formats according to a format specifier and returns the string
|
|
||||||
// as a value that satisfies error.
|
|
||||||
// Errorf also records the stack trace at the point it was called.
|
|
||||||
func Errorf(format string, args ...interface{}) error {
|
|
||||||
return &fundamental{
|
|
||||||
msg: fmt.Sprintf(format, args...),
|
|
||||||
stack: callers(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fundamental is an error that has a message and a stack, but no caller.
|
|
||||||
type fundamental struct {
|
|
||||||
msg string
|
|
||||||
*stack
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fundamental) Error() string { return f.msg }
|
|
||||||
|
|
||||||
func (f *fundamental) Format(s fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 'v':
|
|
||||||
if s.Flag('+') {
|
|
||||||
io.WriteString(s, f.msg)
|
|
||||||
f.stack.Format(s, verb)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case 's':
|
|
||||||
io.WriteString(s, f.msg)
|
|
||||||
case 'q':
|
|
||||||
fmt.Fprintf(s, "%q", f.msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithStack annotates err with a stack trace at the point WithStack was called.
|
|
||||||
// If err is nil, WithStack returns nil.
|
|
||||||
func WithStack(err error) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &withStack{
|
|
||||||
err,
|
|
||||||
callers(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type withStack struct {
|
|
||||||
error
|
|
||||||
*stack
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *withStack) Cause() error { return w.error }
|
|
||||||
|
|
||||||
func (w *withStack) Format(s fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 'v':
|
|
||||||
if s.Flag('+') {
|
|
||||||
fmt.Fprintf(s, "%+v", w.Cause())
|
|
||||||
w.stack.Format(s, verb)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case 's':
|
|
||||||
io.WriteString(s, w.Error())
|
|
||||||
case 'q':
|
|
||||||
fmt.Fprintf(s, "%q", w.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrap returns an error annotating err with a stack trace
|
|
||||||
// at the point Wrap is called, and the supplied message.
|
|
||||||
// If err is nil, Wrap returns nil.
|
|
||||||
func Wrap(err error, message string) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = &withMessage{
|
|
||||||
cause: err,
|
|
||||||
msg: message,
|
|
||||||
}
|
|
||||||
return &withStack{
|
|
||||||
err,
|
|
||||||
callers(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wrapf returns an error annotating err with a stack trace
|
|
||||||
// at the point Wrapf is call, and the format specifier.
|
|
||||||
// If err is nil, Wrapf returns nil.
|
|
||||||
func Wrapf(err error, format string, args ...interface{}) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
err = &withMessage{
|
|
||||||
cause: err,
|
|
||||||
msg: fmt.Sprintf(format, args...),
|
|
||||||
}
|
|
||||||
return &withStack{
|
|
||||||
err,
|
|
||||||
callers(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithMessage annotates err with a new message.
|
|
||||||
// If err is nil, WithMessage returns nil.
|
|
||||||
func WithMessage(err error, message string) error {
|
|
||||||
if err == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return &withMessage{
|
|
||||||
cause: err,
|
|
||||||
msg: message,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type withMessage struct {
|
|
||||||
cause error
|
|
||||||
msg string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *withMessage) Error() string { return w.msg + ": " + w.cause.Error() }
|
|
||||||
func (w *withMessage) Cause() error { return w.cause }
|
|
||||||
|
|
||||||
func (w *withMessage) Format(s fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 'v':
|
|
||||||
if s.Flag('+') {
|
|
||||||
fmt.Fprintf(s, "%+v\n", w.Cause())
|
|
||||||
io.WriteString(s, w.msg)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fallthrough
|
|
||||||
case 's', 'q':
|
|
||||||
io.WriteString(s, w.Error())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cause returns the underlying cause of the error, if possible.
|
|
||||||
// An error value has a cause if it implements the following
|
|
||||||
// interface:
|
|
||||||
//
|
|
||||||
// type causer interface {
|
|
||||||
// Cause() error
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// If the error does not implement Cause, the original error will
|
|
||||||
// be returned. If the error is nil, nil will be returned without further
|
|
||||||
// investigation.
|
|
||||||
func Cause(err error) error {
|
|
||||||
type causer interface {
|
|
||||||
Cause() error
|
|
||||||
}
|
|
||||||
|
|
||||||
for err != nil {
|
|
||||||
cause, ok := err.(causer)
|
|
||||||
if !ok {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
err = cause.Cause()
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
@ -1,178 +0,0 @@
|
|||||||
package errors
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"path"
|
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Frame represents a program counter inside a stack frame.
|
|
||||||
type Frame uintptr
|
|
||||||
|
|
||||||
// pc returns the program counter for this frame;
|
|
||||||
// multiple frames may have the same PC value.
|
|
||||||
func (f Frame) pc() uintptr { return uintptr(f) - 1 }
|
|
||||||
|
|
||||||
// file returns the full path to the file that contains the
|
|
||||||
// function for this Frame's pc.
|
|
||||||
func (f Frame) file() string {
|
|
||||||
fn := runtime.FuncForPC(f.pc())
|
|
||||||
if fn == nil {
|
|
||||||
return "unknown"
|
|
||||||
}
|
|
||||||
file, _ := fn.FileLine(f.pc())
|
|
||||||
return file
|
|
||||||
}
|
|
||||||
|
|
||||||
// line returns the line number of source code of the
|
|
||||||
// function for this Frame's pc.
|
|
||||||
func (f Frame) line() int {
|
|
||||||
fn := runtime.FuncForPC(f.pc())
|
|
||||||
if fn == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
_, line := fn.FileLine(f.pc())
|
|
||||||
return line
|
|
||||||
}
|
|
||||||
|
|
||||||
// Format formats the frame according to the fmt.Formatter interface.
|
|
||||||
//
|
|
||||||
// %s source file
|
|
||||||
// %d source line
|
|
||||||
// %n function name
|
|
||||||
// %v equivalent to %s:%d
|
|
||||||
//
|
|
||||||
// Format accepts flags that alter the printing of some verbs, as follows:
|
|
||||||
//
|
|
||||||
// %+s path of source file relative to the compile time GOPATH
|
|
||||||
// %+v equivalent to %+s:%d
|
|
||||||
func (f Frame) Format(s fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 's':
|
|
||||||
switch {
|
|
||||||
case s.Flag('+'):
|
|
||||||
pc := f.pc()
|
|
||||||
fn := runtime.FuncForPC(pc)
|
|
||||||
if fn == nil {
|
|
||||||
io.WriteString(s, "unknown")
|
|
||||||
} else {
|
|
||||||
file, _ := fn.FileLine(pc)
|
|
||||||
fmt.Fprintf(s, "%s\n\t%s", fn.Name(), file)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
io.WriteString(s, path.Base(f.file()))
|
|
||||||
}
|
|
||||||
case 'd':
|
|
||||||
fmt.Fprintf(s, "%d", f.line())
|
|
||||||
case 'n':
|
|
||||||
name := runtime.FuncForPC(f.pc()).Name()
|
|
||||||
io.WriteString(s, funcname(name))
|
|
||||||
case 'v':
|
|
||||||
f.Format(s, 's')
|
|
||||||
io.WriteString(s, ":")
|
|
||||||
f.Format(s, 'd')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// StackTrace is stack of Frames from innermost (newest) to outermost (oldest).
|
|
||||||
type StackTrace []Frame
|
|
||||||
|
|
||||||
func (st StackTrace) Format(s fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 'v':
|
|
||||||
switch {
|
|
||||||
case s.Flag('+'):
|
|
||||||
for _, f := range st {
|
|
||||||
fmt.Fprintf(s, "\n%+v", f)
|
|
||||||
}
|
|
||||||
case s.Flag('#'):
|
|
||||||
fmt.Fprintf(s, "%#v", []Frame(st))
|
|
||||||
default:
|
|
||||||
fmt.Fprintf(s, "%v", []Frame(st))
|
|
||||||
}
|
|
||||||
case 's':
|
|
||||||
fmt.Fprintf(s, "%s", []Frame(st))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// stack represents a stack of program counters.
|
|
||||||
type stack []uintptr
|
|
||||||
|
|
||||||
func (s *stack) Format(st fmt.State, verb rune) {
|
|
||||||
switch verb {
|
|
||||||
case 'v':
|
|
||||||
switch {
|
|
||||||
case st.Flag('+'):
|
|
||||||
for _, pc := range *s {
|
|
||||||
f := Frame(pc)
|
|
||||||
fmt.Fprintf(st, "\n%+v", f)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *stack) StackTrace() StackTrace {
|
|
||||||
f := make([]Frame, len(*s))
|
|
||||||
for i := 0; i < len(f); i++ {
|
|
||||||
f[i] = Frame((*s)[i])
|
|
||||||
}
|
|
||||||
return f
|
|
||||||
}
|
|
||||||
|
|
||||||
func callers() *stack {
|
|
||||||
const depth = 32
|
|
||||||
var pcs [depth]uintptr
|
|
||||||
n := runtime.Callers(3, pcs[:])
|
|
||||||
var st stack = pcs[0:n]
|
|
||||||
return &st
|
|
||||||
}
|
|
||||||
|
|
||||||
// funcname removes the path prefix component of a function's name reported by func.Name().
|
|
||||||
func funcname(name string) string {
|
|
||||||
i := strings.LastIndex(name, "/")
|
|
||||||
name = name[i+1:]
|
|
||||||
i = strings.Index(name, ".")
|
|
||||||
return name[i+1:]
|
|
||||||
}
|
|
||||||
|
|
||||||
func trimGOPATH(name, file string) string {
|
|
||||||
// Here we want to get the source file path relative to the compile time
|
|
||||||
// GOPATH. As of Go 1.6.x there is no direct way to know the compiled
|
|
||||||
// GOPATH at runtime, but we can infer the number of path segments in the
|
|
||||||
// GOPATH. We note that fn.Name() returns the function name qualified by
|
|
||||||
// the import path, which does not include the GOPATH. Thus we can trim
|
|
||||||
// segments from the beginning of the file path until the number of path
|
|
||||||
// separators remaining is one more than the number of path separators in
|
|
||||||
// the function name. For example, given:
|
|
||||||
//
|
|
||||||
// GOPATH /home/user
|
|
||||||
// file /home/user/src/pkg/sub/file.go
|
|
||||||
// fn.Name() pkg/sub.Type.Method
|
|
||||||
//
|
|
||||||
// We want to produce:
|
|
||||||
//
|
|
||||||
// pkg/sub/file.go
|
|
||||||
//
|
|
||||||
// From this we can easily see that fn.Name() has one less path separator
|
|
||||||
// than our desired output. We count separators from the end of the file
|
|
||||||
// path until it finds two more than in the function name and then move
|
|
||||||
// one character forward to preserve the initial path segment without a
|
|
||||||
// leading separator.
|
|
||||||
const sep = "/"
|
|
||||||
goal := strings.Count(name, sep) + 2
|
|
||||||
i := len(file)
|
|
||||||
for n := 0; n < goal; n++ {
|
|
||||||
i = strings.LastIndex(file[:i], sep)
|
|
||||||
if i == -1 {
|
|
||||||
// not enough separators found, set i so that the slice expression
|
|
||||||
// below leaves file unmodified
|
|
||||||
i = -len(sep)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// get back to 0 or trim the leading separator
|
|
||||||
file = file[i+len(sep):]
|
|
||||||
return file
|
|
||||||
}
|
|
@ -1,378 +0,0 @@
|
|||||||
# Change Log
|
|
||||||
|
|
||||||
**ATTN**: This project uses [semantic versioning](http://semver.org/).
|
|
||||||
|
|
||||||
## [Unreleased]
|
|
||||||
|
|
||||||
|
|
||||||
## [1.19.0] - 2016-11-12
|
|
||||||
### Added
|
|
||||||
- `FlagsByName` was added to make it easy to sort flags (e.g. `sort.Sort(cli.FlagsByName(app.Flags))`)
|
|
||||||
- A `Description` field was added to `App` for a more detailed description of
|
|
||||||
the application (similar to the existing `Description` field on `Command`)
|
|
||||||
- Flag type code generation via `go generate`
|
|
||||||
- Write to stderr and exit 1 if action returns non-nil error
|
|
||||||
- Added support for TOML to the `altsrc` loader
|
|
||||||
- `SkipArgReorder` was added to allow users to skip the argument reordering.
|
|
||||||
This is useful if you want to consider all "flags" after an argument as
|
|
||||||
arguments rather than flags (the default behavior of the stdlib `flag`
|
|
||||||
library). This is backported functionality from the [removal of the flag
|
|
||||||
reordering](https://github.com/urfave/cli/pull/398) in the unreleased version
|
|
||||||
2
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Raise minimum tested/supported Go version to 1.2+
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Consider empty environment variables as set (previously environment variables
|
|
||||||
with the equivalent of `""` would be skipped rather than their value used).
|
|
||||||
- Return an error if the value in a given environment variable cannot be parsed
|
|
||||||
as the flag type. Previously these errors were silently swallowed.
|
|
||||||
- Print full error when an invalid flag is specified (which includes the invalid flag)
|
|
||||||
- `App.Writer` defaults to `stdout` when `nil`
|
|
||||||
- If no action is specified on a command or app, the help is now printed instead of `panic`ing
|
|
||||||
- `App.Metadata` is initialized automatically now (previously was `nil` unless initialized)
|
|
||||||
- Correctly show help message if `-h` is provided to a subcommand
|
|
||||||
- `context.(Global)IsSet` now respects environment variables. Previously it
|
|
||||||
would return `false` if a flag was specified in the environment rather than
|
|
||||||
as an argument
|
|
||||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
|
||||||
- `altsrc`s import paths were updated to use `gopkg.in/urfave/cli.v1`. This
|
|
||||||
fixes issues that occurred when `gopkg.in/urfave/cli.v1` was imported as well
|
|
||||||
as `altsrc` where Go would complain that the types didn't match
|
|
||||||
|
|
||||||
## [1.18.1] - 2016-08-28
|
|
||||||
### Fixed
|
|
||||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user (backported)
|
|
||||||
|
|
||||||
## [1.18.0] - 2016-06-27
|
|
||||||
### Added
|
|
||||||
- `./runtests` test runner with coverage tracking by default
|
|
||||||
- testing on OS X
|
|
||||||
- testing on Windows
|
|
||||||
- `UintFlag`, `Uint64Flag`, and `Int64Flag` types and supporting code
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Use spaces for alignment in help/usage output instead of tabs, making the
|
|
||||||
output alignment consistent regardless of tab width
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Printing of command aliases in help text
|
|
||||||
- Printing of visible flags for both struct and struct pointer flags
|
|
||||||
- Display the `help` subcommand when using `CommandCategories`
|
|
||||||
- No longer swallows `panic`s that occur within the `Action`s themselves when
|
|
||||||
detecting the signature of the `Action` field
|
|
||||||
|
|
||||||
## [1.17.1] - 2016-08-28
|
|
||||||
### Fixed
|
|
||||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
|
||||||
|
|
||||||
## [1.17.0] - 2016-05-09
|
|
||||||
### Added
|
|
||||||
- Pluggable flag-level help text rendering via `cli.DefaultFlagStringFunc`
|
|
||||||
- `context.GlobalBoolT` was added as an analogue to `context.GlobalBool`
|
|
||||||
- Support for hiding commands by setting `Hidden: true` -- this will hide the
|
|
||||||
commands in help output
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- `Float64Flag`, `IntFlag`, and `DurationFlag` default values are no longer
|
|
||||||
quoted in help text output.
|
|
||||||
- All flag types now include `(default: {value})` strings following usage when a
|
|
||||||
default value can be (reasonably) detected.
|
|
||||||
- `IntSliceFlag` and `StringSliceFlag` usage strings are now more consistent
|
|
||||||
with non-slice flag types
|
|
||||||
- Apps now exit with a code of 3 if an unknown subcommand is specified
|
|
||||||
(previously they printed "No help topic for...", but still exited 0. This
|
|
||||||
makes it easier to script around apps built using `cli` since they can trust
|
|
||||||
that a 0 exit code indicated a successful execution.
|
|
||||||
- cleanups based on [Go Report Card
|
|
||||||
feedback](https://goreportcard.com/report/github.com/urfave/cli)
|
|
||||||
|
|
||||||
## [1.16.1] - 2016-08-28
|
|
||||||
### Fixed
|
|
||||||
- Removed deprecation warnings to STDERR to avoid them leaking to the end-user
|
|
||||||
|
|
||||||
## [1.16.0] - 2016-05-02
|
|
||||||
### Added
|
|
||||||
- `Hidden` field on all flag struct types to omit from generated help text
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- `BashCompletionFlag` (`--enable-bash-completion`) is now omitted from
|
|
||||||
generated help text via the `Hidden` field
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- handling of error values in `HandleAction` and `HandleExitCoder`
|
|
||||||
|
|
||||||
## [1.15.0] - 2016-04-30
|
|
||||||
### Added
|
|
||||||
- This file!
|
|
||||||
- Support for placeholders in flag usage strings
|
|
||||||
- `App.Metadata` map for arbitrary data/state management
|
|
||||||
- `Set` and `GlobalSet` methods on `*cli.Context` for altering values after
|
|
||||||
parsing.
|
|
||||||
- Support for nested lookup of dot-delimited keys in structures loaded from
|
|
||||||
YAML.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- The `App.Action` and `Command.Action` now prefer a return signature of
|
|
||||||
`func(*cli.Context) error`, as defined by `cli.ActionFunc`. If a non-nil
|
|
||||||
`error` is returned, there may be two outcomes:
|
|
||||||
- If the error fulfills `cli.ExitCoder`, then `os.Exit` will be called
|
|
||||||
automatically
|
|
||||||
- Else the error is bubbled up and returned from `App.Run`
|
|
||||||
- Specifying an `Action` with the legacy return signature of
|
|
||||||
`func(*cli.Context)` will produce a deprecation message to stderr
|
|
||||||
- Specifying an `Action` that is not a `func` type will produce a non-zero exit
|
|
||||||
from `App.Run`
|
|
||||||
- Specifying an `Action` func that has an invalid (input) signature will
|
|
||||||
produce a non-zero exit from `App.Run`
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
- <a name="deprecated-cli-app-runandexitonerror"></a>
|
|
||||||
`cli.App.RunAndExitOnError`, which should now be done by returning an error
|
|
||||||
that fulfills `cli.ExitCoder` to `cli.App.Run`.
|
|
||||||
- <a name="deprecated-cli-app-action-signature"></a> the legacy signature for
|
|
||||||
`cli.App.Action` of `func(*cli.Context)`, which should now have a return
|
|
||||||
signature of `func(*cli.Context) error`, as defined by `cli.ActionFunc`.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Added missing `*cli.Context.GlobalFloat64` method
|
|
||||||
|
|
||||||
## [1.14.0] - 2016-04-03 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Codebeat badge
|
|
||||||
- Support for categorization via `CategorizedHelp` and `Categories` on app.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Use `filepath.Base` instead of `path.Base` in `Name` and `HelpName`.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Ensure version is not shown in help text when `HideVersion` set.
|
|
||||||
|
|
||||||
## [1.13.0] - 2016-03-06 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- YAML file input support.
|
|
||||||
- `NArg` method on context.
|
|
||||||
|
|
||||||
## [1.12.0] - 2016-02-17 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Custom usage error handling.
|
|
||||||
- Custom text support in `USAGE` section of help output.
|
|
||||||
- Improved help messages for empty strings.
|
|
||||||
- AppVeyor CI configuration.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Removed `panic` from default help printer func.
|
|
||||||
- De-duping and optimizations.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Correctly handle `Before`/`After` at command level when no subcommands.
|
|
||||||
- Case of literal `-` argument causing flag reordering.
|
|
||||||
- Environment variable hints on Windows.
|
|
||||||
- Docs updates.
|
|
||||||
|
|
||||||
## [1.11.1] - 2015-12-21 (backfilled 2016-04-25)
|
|
||||||
### Changed
|
|
||||||
- Use `path.Base` in `Name` and `HelpName`
|
|
||||||
- Export `GetName` on flag types.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Flag parsing when skipping is enabled.
|
|
||||||
- Test output cleanup.
|
|
||||||
- Move completion check to account for empty input case.
|
|
||||||
|
|
||||||
## [1.11.0] - 2015-11-15 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Destination scan support for flags.
|
|
||||||
- Testing against `tip` in Travis CI config.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Go version in Travis CI config.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Removed redundant tests.
|
|
||||||
- Use correct example naming in tests.
|
|
||||||
|
|
||||||
## [1.10.2] - 2015-10-29 (backfilled 2016-04-25)
|
|
||||||
### Fixed
|
|
||||||
- Remove unused var in bash completion.
|
|
||||||
|
|
||||||
## [1.10.1] - 2015-10-21 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Coverage and reference logos in README.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Use specified values in help and version parsing.
|
|
||||||
- Only display app version and help message once.
|
|
||||||
|
|
||||||
## [1.10.0] - 2015-10-06 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- More tests for existing functionality.
|
|
||||||
- `ArgsUsage` at app and command level for help text flexibility.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Honor `HideHelp` and `HideVersion` in `App.Run`.
|
|
||||||
- Remove juvenile word from README.
|
|
||||||
|
|
||||||
## [1.9.0] - 2015-09-08 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- `FullName` on command with accompanying help output update.
|
|
||||||
- Set default `$PROG` in bash completion.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Docs formatting.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Removed self-referential imports in tests.
|
|
||||||
|
|
||||||
## [1.8.0] - 2015-06-30 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Support for `Copyright` at app level.
|
|
||||||
- `Parent` func at context level to walk up context lineage.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Global flag processing at top level.
|
|
||||||
|
|
||||||
## [1.7.1] - 2015-06-11 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Aggregate errors from `Before`/`After` funcs.
|
|
||||||
- Doc comments on flag structs.
|
|
||||||
- Include non-global flags when checking version and help.
|
|
||||||
- Travis CI config updates.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Ensure slice type flags have non-nil values.
|
|
||||||
- Collect global flags from the full command hierarchy.
|
|
||||||
- Docs prose.
|
|
||||||
|
|
||||||
## [1.7.0] - 2015-05-03 (backfilled 2016-04-25)
|
|
||||||
### Changed
|
|
||||||
- `HelpPrinter` signature includes output writer.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Specify go 1.1+ in docs.
|
|
||||||
- Set `Writer` when running command as app.
|
|
||||||
|
|
||||||
## [1.6.0] - 2015-03-23 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Multiple author support.
|
|
||||||
- `NumFlags` at context level.
|
|
||||||
- `Aliases` at command level.
|
|
||||||
|
|
||||||
### Deprecated
|
|
||||||
- `ShortName` at command level.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Subcommand help output.
|
|
||||||
- Backward compatible support for deprecated `Author` and `Email` fields.
|
|
||||||
- Docs regarding `Names`/`Aliases`.
|
|
||||||
|
|
||||||
## [1.5.0] - 2015-02-20 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- `After` hook func support at app and command level.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Use parsed context when running command as subcommand.
|
|
||||||
- Docs prose.
|
|
||||||
|
|
||||||
## [1.4.1] - 2015-01-09 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Support for hiding `-h / --help` flags, but not `help` subcommand.
|
|
||||||
- Stop flag parsing after `--`.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Help text for generic flags to specify single value.
|
|
||||||
- Use double quotes in output for defaults.
|
|
||||||
- Use `ParseInt` instead of `ParseUint` for int environment var values.
|
|
||||||
- Use `0` as base when parsing int environment var values.
|
|
||||||
|
|
||||||
## [1.4.0] - 2014-12-12 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Support for environment variable lookup "cascade".
|
|
||||||
- Support for `Stdout` on app for output redirection.
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
- Print command help instead of app help in `ShowCommandHelp`.
|
|
||||||
|
|
||||||
## [1.3.1] - 2014-11-13 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- Docs and example code updates.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Default `-v / --version` flag made optional.
|
|
||||||
|
|
||||||
## [1.3.0] - 2014-08-10 (backfilled 2016-04-25)
|
|
||||||
### Added
|
|
||||||
- `FlagNames` at context level.
|
|
||||||
- Exposed `VersionPrinter` var for more control over version output.
|
|
||||||
- Zsh completion hook.
|
|
||||||
- `AUTHOR` section in default app help template.
|
|
||||||
- Contribution guidelines.
|
|
||||||
- `DurationFlag` type.
|
|
||||||
|
|
||||||
## [1.2.0] - 2014-08-02
|
|
||||||
### Added
|
|
||||||
- Support for environment variable defaults on flags plus tests.
|
|
||||||
|
|
||||||
## [1.1.0] - 2014-07-15
|
|
||||||
### Added
|
|
||||||
- Bash completion.
|
|
||||||
- Optional hiding of built-in help command.
|
|
||||||
- Optional skipping of flag parsing at command level.
|
|
||||||
- `Author`, `Email`, and `Compiled` metadata on app.
|
|
||||||
- `Before` hook func support at app and command level.
|
|
||||||
- `CommandNotFound` func support at app level.
|
|
||||||
- Command reference available on context.
|
|
||||||
- `GenericFlag` type.
|
|
||||||
- `Float64Flag` type.
|
|
||||||
- `BoolTFlag` type.
|
|
||||||
- `IsSet` flag helper on context.
|
|
||||||
- More flag lookup funcs at context level.
|
|
||||||
- More tests & docs.
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
- Help template updates to account for presence/absence of flags.
|
|
||||||
- Separated subcommand help template.
|
|
||||||
- Exposed `HelpPrinter` var for more control over help output.
|
|
||||||
|
|
||||||
## [1.0.0] - 2013-11-01
|
|
||||||
### Added
|
|
||||||
- `help` flag in default app flag set and each command flag set.
|
|
||||||
- Custom handling of argument parsing errors.
|
|
||||||
- Command lookup by name at app level.
|
|
||||||
- `StringSliceFlag` type and supporting `StringSlice` type.
|
|
||||||
- `IntSliceFlag` type and supporting `IntSlice` type.
|
|
||||||
- Slice type flag lookups by name at context level.
|
|
||||||
- Export of app and command help functions.
|
|
||||||
- More tests & docs.
|
|
||||||
|
|
||||||
## 0.1.0 - 2013-07-22
|
|
||||||
### Added
|
|
||||||
- Initial implementation.
|
|
||||||
|
|
||||||
[Unreleased]: https://github.com/urfave/cli/compare/v1.18.0...HEAD
|
|
||||||
[1.18.0]: https://github.com/urfave/cli/compare/v1.17.0...v1.18.0
|
|
||||||
[1.17.0]: https://github.com/urfave/cli/compare/v1.16.0...v1.17.0
|
|
||||||
[1.16.0]: https://github.com/urfave/cli/compare/v1.15.0...v1.16.0
|
|
||||||
[1.15.0]: https://github.com/urfave/cli/compare/v1.14.0...v1.15.0
|
|
||||||
[1.14.0]: https://github.com/urfave/cli/compare/v1.13.0...v1.14.0
|
|
||||||
[1.13.0]: https://github.com/urfave/cli/compare/v1.12.0...v1.13.0
|
|
||||||
[1.12.0]: https://github.com/urfave/cli/compare/v1.11.1...v1.12.0
|
|
||||||
[1.11.1]: https://github.com/urfave/cli/compare/v1.11.0...v1.11.1
|
|
||||||
[1.11.0]: https://github.com/urfave/cli/compare/v1.10.2...v1.11.0
|
|
||||||
[1.10.2]: https://github.com/urfave/cli/compare/v1.10.1...v1.10.2
|
|
||||||
[1.10.1]: https://github.com/urfave/cli/compare/v1.10.0...v1.10.1
|
|
||||||
[1.10.0]: https://github.com/urfave/cli/compare/v1.9.0...v1.10.0
|
|
||||||
[1.9.0]: https://github.com/urfave/cli/compare/v1.8.0...v1.9.0
|
|
||||||
[1.8.0]: https://github.com/urfave/cli/compare/v1.7.1...v1.8.0
|
|
||||||
[1.7.1]: https://github.com/urfave/cli/compare/v1.7.0...v1.7.1
|
|
||||||
[1.7.0]: https://github.com/urfave/cli/compare/v1.6.0...v1.7.0
|
|
||||||
[1.6.0]: https://github.com/urfave/cli/compare/v1.5.0...v1.6.0
|
|
||||||
[1.5.0]: https://github.com/urfave/cli/compare/v1.4.1...v1.5.0
|
|
||||||
[1.4.1]: https://github.com/urfave/cli/compare/v1.4.0...v1.4.1
|
|
||||||
[1.4.0]: https://github.com/urfave/cli/compare/v1.3.1...v1.4.0
|
|
||||||
[1.3.1]: https://github.com/urfave/cli/compare/v1.3.0...v1.3.1
|
|
||||||
[1.3.0]: https://github.com/urfave/cli/compare/v1.2.0...v1.3.0
|
|
||||||
[1.2.0]: https://github.com/urfave/cli/compare/v1.1.0...v1.2.0
|
|
||||||
[1.1.0]: https://github.com/urfave/cli/compare/v1.0.0...v1.1.0
|
|
||||||
[1.0.0]: https://github.com/urfave/cli/compare/v0.1.0...v1.0.0
|
|
@ -1,21 +0,0 @@
|
|||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2016 Jeremy Saenz & Contributors
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
File diff suppressed because it is too large
Load Diff
@ -1,490 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"sort"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
changeLogURL = "https://github.com/urfave/cli/blob/master/CHANGELOG.md"
|
|
||||||
appActionDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-action-signature", changeLogURL)
|
|
||||||
runAndExitOnErrorDeprecationURL = fmt.Sprintf("%s#deprecated-cli-app-runandexitonerror", changeLogURL)
|
|
||||||
|
|
||||||
contactSysadmin = "This is an error in the application. Please contact the distributor of this application if this is not you."
|
|
||||||
|
|
||||||
errInvalidActionType = NewExitError("ERROR invalid Action type. "+
|
|
||||||
fmt.Sprintf("Must be `func(*Context`)` or `func(*Context) error). %s", contactSysadmin)+
|
|
||||||
fmt.Sprintf("See %s", appActionDeprecationURL), 2)
|
|
||||||
)
|
|
||||||
|
|
||||||
// App is the main structure of a cli application. It is recommended that
|
|
||||||
// an app be created with the cli.NewApp() function
|
|
||||||
type App struct {
|
|
||||||
// The name of the program. Defaults to path.Base(os.Args[0])
|
|
||||||
Name string
|
|
||||||
// Full name of command for help, defaults to Name
|
|
||||||
HelpName string
|
|
||||||
// Description of the program.
|
|
||||||
Usage string
|
|
||||||
// Text to override the USAGE section of help
|
|
||||||
UsageText string
|
|
||||||
// Description of the program argument format.
|
|
||||||
ArgsUsage string
|
|
||||||
// Version of the program
|
|
||||||
Version string
|
|
||||||
// Description of the program
|
|
||||||
Description string
|
|
||||||
// List of commands to execute
|
|
||||||
Commands []Command
|
|
||||||
// List of flags to parse
|
|
||||||
Flags []Flag
|
|
||||||
// Boolean to enable bash completion commands
|
|
||||||
EnableBashCompletion bool
|
|
||||||
// Boolean to hide built-in help command
|
|
||||||
HideHelp bool
|
|
||||||
// Boolean to hide built-in version flag and the VERSION section of help
|
|
||||||
HideVersion bool
|
|
||||||
// Populate on app startup, only gettable through method Categories()
|
|
||||||
categories CommandCategories
|
|
||||||
// An action to execute when the bash-completion flag is set
|
|
||||||
BashComplete BashCompleteFunc
|
|
||||||
// An action to execute before any subcommands are run, but after the context is ready
|
|
||||||
// If a non-nil error is returned, no subcommands are run
|
|
||||||
Before BeforeFunc
|
|
||||||
// An action to execute after any subcommands are run, but after the subcommand has finished
|
|
||||||
// It is run even if Action() panics
|
|
||||||
After AfterFunc
|
|
||||||
|
|
||||||
// The action to execute when no subcommands are specified
|
|
||||||
// Expects a `cli.ActionFunc` but will accept the *deprecated* signature of `func(*cli.Context) {}`
|
|
||||||
// *Note*: support for the deprecated `Action` signature will be removed in a future version
|
|
||||||
Action interface{}
|
|
||||||
|
|
||||||
// Execute this function if the proper command cannot be found
|
|
||||||
CommandNotFound CommandNotFoundFunc
|
|
||||||
// Execute this function if an usage error occurs
|
|
||||||
OnUsageError OnUsageErrorFunc
|
|
||||||
// Compilation date
|
|
||||||
Compiled time.Time
|
|
||||||
// List of all authors who contributed
|
|
||||||
Authors []Author
|
|
||||||
// Copyright of the binary if any
|
|
||||||
Copyright string
|
|
||||||
// Name of Author (Note: Use App.Authors, this is deprecated)
|
|
||||||
Author string
|
|
||||||
// Email of Author (Note: Use App.Authors, this is deprecated)
|
|
||||||
Email string
|
|
||||||
// Writer writer to write output to
|
|
||||||
Writer io.Writer
|
|
||||||
// ErrWriter writes error output
|
|
||||||
ErrWriter io.Writer
|
|
||||||
// Other custom info
|
|
||||||
Metadata map[string]interface{}
|
|
||||||
|
|
||||||
didSetup bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tries to find out when this binary was compiled.
|
|
||||||
// Returns the current time if it fails to find it.
|
|
||||||
func compileTime() time.Time {
|
|
||||||
info, err := os.Stat(os.Args[0])
|
|
||||||
if err != nil {
|
|
||||||
return time.Now()
|
|
||||||
}
|
|
||||||
return info.ModTime()
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewApp creates a new cli Application with some reasonable defaults for Name,
|
|
||||||
// Usage, Version and Action.
|
|
||||||
func NewApp() *App {
|
|
||||||
return &App{
|
|
||||||
Name: filepath.Base(os.Args[0]),
|
|
||||||
HelpName: filepath.Base(os.Args[0]),
|
|
||||||
Usage: "A new cli application",
|
|
||||||
UsageText: "",
|
|
||||||
Version: "0.0.0",
|
|
||||||
BashComplete: DefaultAppComplete,
|
|
||||||
Action: helpCommand.Action,
|
|
||||||
Compiled: compileTime(),
|
|
||||||
Writer: os.Stdout,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup runs initialization code to ensure all data structures are ready for
|
|
||||||
// `Run` or inspection prior to `Run`. It is internally called by `Run`, but
|
|
||||||
// will return early if setup has already happened.
|
|
||||||
func (a *App) Setup() {
|
|
||||||
if a.didSetup {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
a.didSetup = true
|
|
||||||
|
|
||||||
if a.Author != "" || a.Email != "" {
|
|
||||||
a.Authors = append(a.Authors, Author{Name: a.Author, Email: a.Email})
|
|
||||||
}
|
|
||||||
|
|
||||||
newCmds := []Command{}
|
|
||||||
for _, c := range a.Commands {
|
|
||||||
if c.HelpName == "" {
|
|
||||||
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
|
||||||
}
|
|
||||||
newCmds = append(newCmds, c)
|
|
||||||
}
|
|
||||||
a.Commands = newCmds
|
|
||||||
|
|
||||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
|
||||||
a.Commands = append(a.Commands, helpCommand)
|
|
||||||
if (HelpFlag != BoolFlag{}) {
|
|
||||||
a.appendFlag(HelpFlag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.EnableBashCompletion {
|
|
||||||
a.appendFlag(BashCompletionFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !a.HideVersion {
|
|
||||||
a.appendFlag(VersionFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
a.categories = CommandCategories{}
|
|
||||||
for _, command := range a.Commands {
|
|
||||||
a.categories = a.categories.AddCommand(command.Category, command)
|
|
||||||
}
|
|
||||||
sort.Sort(a.categories)
|
|
||||||
|
|
||||||
if a.Metadata == nil {
|
|
||||||
a.Metadata = make(map[string]interface{})
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.Writer == nil {
|
|
||||||
a.Writer = os.Stdout
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run is the entry point to the cli app. Parses the arguments slice and routes
|
|
||||||
// to the proper flag/args combination
|
|
||||||
func (a *App) Run(arguments []string) (err error) {
|
|
||||||
a.Setup()
|
|
||||||
|
|
||||||
// parse flags
|
|
||||||
set, err := flagSet(a.Name, a.Flags)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
set.SetOutput(ioutil.Discard)
|
|
||||||
err = set.Parse(arguments[1:])
|
|
||||||
nerr := normalizeFlags(a.Flags, set)
|
|
||||||
context := NewContext(a, set, nil)
|
|
||||||
if nerr != nil {
|
|
||||||
fmt.Fprintln(a.Writer, nerr)
|
|
||||||
ShowAppHelp(context)
|
|
||||||
return nerr
|
|
||||||
}
|
|
||||||
|
|
||||||
if checkCompletions(context) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if a.OnUsageError != nil {
|
|
||||||
err := a.OnUsageError(context, err, false)
|
|
||||||
HandleExitCoder(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
|
||||||
ShowAppHelp(context)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if !a.HideHelp && checkHelp(context) {
|
|
||||||
ShowAppHelp(context)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if !a.HideVersion && checkVersion(context) {
|
|
||||||
ShowVersion(context)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.After != nil {
|
|
||||||
defer func() {
|
|
||||||
if afterErr := a.After(context); afterErr != nil {
|
|
||||||
if err != nil {
|
|
||||||
err = NewMultiError(err, afterErr)
|
|
||||||
} else {
|
|
||||||
err = afterErr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.Before != nil {
|
|
||||||
beforeErr := a.Before(context)
|
|
||||||
if beforeErr != nil {
|
|
||||||
fmt.Fprintf(a.Writer, "%v\n\n", beforeErr)
|
|
||||||
ShowAppHelp(context)
|
|
||||||
HandleExitCoder(beforeErr)
|
|
||||||
err = beforeErr
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
args := context.Args()
|
|
||||||
if args.Present() {
|
|
||||||
name := args.First()
|
|
||||||
c := a.Command(name)
|
|
||||||
if c != nil {
|
|
||||||
return c.Run(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.Action == nil {
|
|
||||||
a.Action = helpCommand.Action
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run default Action
|
|
||||||
err = HandleAction(a.Action, context)
|
|
||||||
|
|
||||||
HandleExitCoder(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunAndExitOnError calls .Run() and exits non-zero if an error was returned
|
|
||||||
//
|
|
||||||
// Deprecated: instead you should return an error that fulfills cli.ExitCoder
|
|
||||||
// to cli.App.Run. This will cause the application to exit with the given eror
|
|
||||||
// code in the cli.ExitCoder
|
|
||||||
func (a *App) RunAndExitOnError() {
|
|
||||||
if err := a.Run(os.Args); err != nil {
|
|
||||||
fmt.Fprintln(a.errWriter(), err)
|
|
||||||
OsExiter(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// RunAsSubcommand invokes the subcommand given the context, parses ctx.Args() to
|
|
||||||
// generate command-specific flags
|
|
||||||
func (a *App) RunAsSubcommand(ctx *Context) (err error) {
|
|
||||||
// append help to commands
|
|
||||||
if len(a.Commands) > 0 {
|
|
||||||
if a.Command(helpCommand.Name) == nil && !a.HideHelp {
|
|
||||||
a.Commands = append(a.Commands, helpCommand)
|
|
||||||
if (HelpFlag != BoolFlag{}) {
|
|
||||||
a.appendFlag(HelpFlag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
newCmds := []Command{}
|
|
||||||
for _, c := range a.Commands {
|
|
||||||
if c.HelpName == "" {
|
|
||||||
c.HelpName = fmt.Sprintf("%s %s", a.HelpName, c.Name)
|
|
||||||
}
|
|
||||||
newCmds = append(newCmds, c)
|
|
||||||
}
|
|
||||||
a.Commands = newCmds
|
|
||||||
|
|
||||||
// append flags
|
|
||||||
if a.EnableBashCompletion {
|
|
||||||
a.appendFlag(BashCompletionFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse flags
|
|
||||||
set, err := flagSet(a.Name, a.Flags)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
set.SetOutput(ioutil.Discard)
|
|
||||||
err = set.Parse(ctx.Args().Tail())
|
|
||||||
nerr := normalizeFlags(a.Flags, set)
|
|
||||||
context := NewContext(a, set, ctx)
|
|
||||||
|
|
||||||
if nerr != nil {
|
|
||||||
fmt.Fprintln(a.Writer, nerr)
|
|
||||||
fmt.Fprintln(a.Writer)
|
|
||||||
if len(a.Commands) > 0 {
|
|
||||||
ShowSubcommandHelp(context)
|
|
||||||
} else {
|
|
||||||
ShowCommandHelp(ctx, context.Args().First())
|
|
||||||
}
|
|
||||||
return nerr
|
|
||||||
}
|
|
||||||
|
|
||||||
if checkCompletions(context) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if a.OnUsageError != nil {
|
|
||||||
err = a.OnUsageError(context, err, true)
|
|
||||||
HandleExitCoder(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintf(a.Writer, "%s %s\n\n", "Incorrect Usage.", err.Error())
|
|
||||||
ShowSubcommandHelp(context)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(a.Commands) > 0 {
|
|
||||||
if checkSubcommandHelp(context) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if checkCommandHelp(ctx, context.Args().First()) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.After != nil {
|
|
||||||
defer func() {
|
|
||||||
afterErr := a.After(context)
|
|
||||||
if afterErr != nil {
|
|
||||||
HandleExitCoder(err)
|
|
||||||
if err != nil {
|
|
||||||
err = NewMultiError(err, afterErr)
|
|
||||||
} else {
|
|
||||||
err = afterErr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if a.Before != nil {
|
|
||||||
beforeErr := a.Before(context)
|
|
||||||
if beforeErr != nil {
|
|
||||||
HandleExitCoder(beforeErr)
|
|
||||||
err = beforeErr
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
args := context.Args()
|
|
||||||
if args.Present() {
|
|
||||||
name := args.First()
|
|
||||||
c := a.Command(name)
|
|
||||||
if c != nil {
|
|
||||||
return c.Run(context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Run default Action
|
|
||||||
err = HandleAction(a.Action, context)
|
|
||||||
|
|
||||||
HandleExitCoder(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Command returns the named command on App. Returns nil if the command does not exist
|
|
||||||
func (a *App) Command(name string) *Command {
|
|
||||||
for _, c := range a.Commands {
|
|
||||||
if c.HasName(name) {
|
|
||||||
return &c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Categories returns a slice containing all the categories with the commands they contain
|
|
||||||
func (a *App) Categories() CommandCategories {
|
|
||||||
return a.categories
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisibleCategories returns a slice of categories and commands that are
|
|
||||||
// Hidden=false
|
|
||||||
func (a *App) VisibleCategories() []*CommandCategory {
|
|
||||||
ret := []*CommandCategory{}
|
|
||||||
for _, category := range a.categories {
|
|
||||||
if visible := func() *CommandCategory {
|
|
||||||
for _, command := range category.Commands {
|
|
||||||
if !command.Hidden {
|
|
||||||
return category
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}(); visible != nil {
|
|
||||||
ret = append(ret, visible)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisibleCommands returns a slice of the Commands with Hidden=false
|
|
||||||
func (a *App) VisibleCommands() []Command {
|
|
||||||
ret := []Command{}
|
|
||||||
for _, command := range a.Commands {
|
|
||||||
if !command.Hidden {
|
|
||||||
ret = append(ret, command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisibleFlags returns a slice of the Flags with Hidden=false
|
|
||||||
func (a *App) VisibleFlags() []Flag {
|
|
||||||
return visibleFlags(a.Flags)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) hasFlag(flag Flag) bool {
|
|
||||||
for _, f := range a.Flags {
|
|
||||||
if flag == f {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) errWriter() io.Writer {
|
|
||||||
|
|
||||||
// When the app ErrWriter is nil use the package level one.
|
|
||||||
if a.ErrWriter == nil {
|
|
||||||
return ErrWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
return a.ErrWriter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *App) appendFlag(flag Flag) {
|
|
||||||
if !a.hasFlag(flag) {
|
|
||||||
a.Flags = append(a.Flags, flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Author represents someone who has contributed to a cli project.
|
|
||||||
type Author struct {
|
|
||||||
Name string // The Authors name
|
|
||||||
Email string // The Authors email
|
|
||||||
}
|
|
||||||
|
|
||||||
// String makes Author comply to the Stringer interface, to allow an easy print in the templating process
|
|
||||||
func (a Author) String() string {
|
|
||||||
e := ""
|
|
||||||
if a.Email != "" {
|
|
||||||
e = " <" + a.Email + ">"
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprintf("%v%v", a.Name, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleAction attempts to figure out which Action signature was used. If
|
|
||||||
// it's an ActionFunc or a func with the legacy signature for Action, the func
|
|
||||||
// is run!
|
|
||||||
func HandleAction(action interface{}, context *Context) (err error) {
|
|
||||||
if a, ok := action.(func(*Context) error); ok {
|
|
||||||
return a(context)
|
|
||||||
} else if a, ok := action.(func(*Context)); ok { // deprecated function signature
|
|
||||||
a(context)
|
|
||||||
return nil
|
|
||||||
} else {
|
|
||||||
return errInvalidActionType
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
version: "{build}"
|
|
||||||
|
|
||||||
os: Windows Server 2012 R2
|
|
||||||
|
|
||||||
clone_folder: c:\gopath\src\github.com\urfave\cli
|
|
||||||
|
|
||||||
environment:
|
|
||||||
GOPATH: C:\gopath
|
|
||||||
GOVERSION: 1.6
|
|
||||||
PYTHON: C:\Python27-x64
|
|
||||||
PYTHON_VERSION: 2.7.x
|
|
||||||
PYTHON_ARCH: 64
|
|
||||||
|
|
||||||
install:
|
|
||||||
- set PATH=%GOPATH%\bin;C:\go\bin;%PATH%
|
|
||||||
- go version
|
|
||||||
- go env
|
|
||||||
- go get github.com/urfave/gfmrun/...
|
|
||||||
- go get -v -t ./...
|
|
||||||
|
|
||||||
build_script:
|
|
||||||
- python runtests vet
|
|
||||||
- python runtests test
|
|
||||||
- python runtests gfmrun
|
|
@ -1,44 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
// CommandCategories is a slice of *CommandCategory.
|
|
||||||
type CommandCategories []*CommandCategory
|
|
||||||
|
|
||||||
// CommandCategory is a category containing commands.
|
|
||||||
type CommandCategory struct {
|
|
||||||
Name string
|
|
||||||
Commands Commands
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CommandCategories) Less(i, j int) bool {
|
|
||||||
return c[i].Name < c[j].Name
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CommandCategories) Len() int {
|
|
||||||
return len(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c CommandCategories) Swap(i, j int) {
|
|
||||||
c[i], c[j] = c[j], c[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// AddCommand adds a command to a category.
|
|
||||||
func (c CommandCategories) AddCommand(category string, command Command) CommandCategories {
|
|
||||||
for _, commandCategory := range c {
|
|
||||||
if commandCategory.Name == category {
|
|
||||||
commandCategory.Commands = append(commandCategory.Commands, command)
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return append(c, &CommandCategory{Name: category, Commands: []Command{command}})
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisibleCommands returns a slice of the Commands with Hidden=false
|
|
||||||
func (c *CommandCategory) VisibleCommands() []Command {
|
|
||||||
ret := []Command{}
|
|
||||||
for _, command := range c.Commands {
|
|
||||||
if !command.Hidden {
|
|
||||||
ret = append(ret, command)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
// Package cli provides a minimal framework for creating and organizing command line
|
|
||||||
// Go applications. cli is designed to be easy to understand and write, the most simple
|
|
||||||
// cli application can be written as follows:
|
|
||||||
// func main() {
|
|
||||||
// cli.NewApp().Run(os.Args)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// Of course this application does not do much, so let's make this an actual application:
|
|
||||||
// func main() {
|
|
||||||
// app := cli.NewApp()
|
|
||||||
// app.Name = "greet"
|
|
||||||
// app.Usage = "say a greeting"
|
|
||||||
// app.Action = func(c *cli.Context) error {
|
|
||||||
// println("Greetings")
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// app.Run(os.Args)
|
|
||||||
// }
|
|
||||||
package cli
|
|
||||||
|
|
||||||
//go:generate python ./generate-flag-types cli -i flag-types.json -o flag_generated.go
|
|
@ -1,291 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io/ioutil"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Command is a subcommand for a cli.App.
|
|
||||||
type Command struct {
|
|
||||||
// The name of the command
|
|
||||||
Name string
|
|
||||||
// short name of the command. Typically one character (deprecated, use `Aliases`)
|
|
||||||
ShortName string
|
|
||||||
// A list of aliases for the command
|
|
||||||
Aliases []string
|
|
||||||
// A short description of the usage of this command
|
|
||||||
Usage string
|
|
||||||
// Custom text to show on USAGE section of help
|
|
||||||
UsageText string
|
|
||||||
// A longer explanation of how the command works
|
|
||||||
Description string
|
|
||||||
// A short description of the arguments of this command
|
|
||||||
ArgsUsage string
|
|
||||||
// The category the command is part of
|
|
||||||
Category string
|
|
||||||
// The function to call when checking for bash command completions
|
|
||||||
BashComplete BashCompleteFunc
|
|
||||||
// An action to execute before any sub-subcommands are run, but after the context is ready
|
|
||||||
// If a non-nil error is returned, no sub-subcommands are run
|
|
||||||
Before BeforeFunc
|
|
||||||
// An action to execute after any subcommands are run, but after the subcommand has finished
|
|
||||||
// It is run even if Action() panics
|
|
||||||
After AfterFunc
|
|
||||||
// The function to call when this command is invoked
|
|
||||||
Action interface{}
|
|
||||||
// TODO: replace `Action: interface{}` with `Action: ActionFunc` once some kind
|
|
||||||
// of deprecation period has passed, maybe?
|
|
||||||
|
|
||||||
// Execute this function if a usage error occurs.
|
|
||||||
OnUsageError OnUsageErrorFunc
|
|
||||||
// List of child commands
|
|
||||||
Subcommands Commands
|
|
||||||
// List of flags to parse
|
|
||||||
Flags []Flag
|
|
||||||
// Treat all flags as normal arguments if true
|
|
||||||
SkipFlagParsing bool
|
|
||||||
// Skip argument reordering which attempts to move flags before arguments,
|
|
||||||
// but only works if all flags appear after all arguments. This behavior was
|
|
||||||
// removed n version 2 since it only works under specific conditions so we
|
|
||||||
// backport here by exposing it as an option for compatibility.
|
|
||||||
SkipArgReorder bool
|
|
||||||
// Boolean to hide built-in help command
|
|
||||||
HideHelp bool
|
|
||||||
// Boolean to hide this command from help or completion
|
|
||||||
Hidden bool
|
|
||||||
|
|
||||||
// Full name of command for help, defaults to full command name, including parent commands.
|
|
||||||
HelpName string
|
|
||||||
commandNamePath []string
|
|
||||||
}
|
|
||||||
|
|
||||||
// FullName returns the full name of the command.
|
|
||||||
// For subcommands this ensures that parent commands are part of the command path
|
|
||||||
func (c Command) FullName() string {
|
|
||||||
if c.commandNamePath == nil {
|
|
||||||
return c.Name
|
|
||||||
}
|
|
||||||
return strings.Join(c.commandNamePath, " ")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Commands is a slice of Command
|
|
||||||
type Commands []Command
|
|
||||||
|
|
||||||
// Run invokes the command given the context, parses ctx.Args() to generate command-specific flags
|
|
||||||
func (c Command) Run(ctx *Context) (err error) {
|
|
||||||
if len(c.Subcommands) > 0 {
|
|
||||||
return c.startApp(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.HideHelp && (HelpFlag != BoolFlag{}) {
|
|
||||||
// append help to flags
|
|
||||||
c.Flags = append(
|
|
||||||
c.Flags,
|
|
||||||
HelpFlag,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.App.EnableBashCompletion {
|
|
||||||
c.Flags = append(c.Flags, BashCompletionFlag)
|
|
||||||
}
|
|
||||||
|
|
||||||
set, err := flagSet(c.Name, c.Flags)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
set.SetOutput(ioutil.Discard)
|
|
||||||
|
|
||||||
if c.SkipFlagParsing {
|
|
||||||
err = set.Parse(append([]string{"--"}, ctx.Args().Tail()...))
|
|
||||||
} else if !c.SkipArgReorder {
|
|
||||||
firstFlagIndex := -1
|
|
||||||
terminatorIndex := -1
|
|
||||||
for index, arg := range ctx.Args() {
|
|
||||||
if arg == "--" {
|
|
||||||
terminatorIndex = index
|
|
||||||
break
|
|
||||||
} else if arg == "-" {
|
|
||||||
// Do nothing. A dash alone is not really a flag.
|
|
||||||
continue
|
|
||||||
} else if strings.HasPrefix(arg, "-") && firstFlagIndex == -1 {
|
|
||||||
firstFlagIndex = index
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if firstFlagIndex > -1 {
|
|
||||||
args := ctx.Args()
|
|
||||||
regularArgs := make([]string, len(args[1:firstFlagIndex]))
|
|
||||||
copy(regularArgs, args[1:firstFlagIndex])
|
|
||||||
|
|
||||||
var flagArgs []string
|
|
||||||
if terminatorIndex > -1 {
|
|
||||||
flagArgs = args[firstFlagIndex:terminatorIndex]
|
|
||||||
regularArgs = append(regularArgs, args[terminatorIndex:]...)
|
|
||||||
} else {
|
|
||||||
flagArgs = args[firstFlagIndex:]
|
|
||||||
}
|
|
||||||
|
|
||||||
err = set.Parse(append(flagArgs, regularArgs...))
|
|
||||||
} else {
|
|
||||||
err = set.Parse(ctx.Args().Tail())
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
err = set.Parse(ctx.Args().Tail())
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
if c.OnUsageError != nil {
|
|
||||||
err := c.OnUsageError(ctx, err, false)
|
|
||||||
HandleExitCoder(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fmt.Fprintln(ctx.App.Writer, "Incorrect Usage:", err.Error())
|
|
||||||
fmt.Fprintln(ctx.App.Writer)
|
|
||||||
ShowCommandHelp(ctx, c.Name)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
nerr := normalizeFlags(c.Flags, set)
|
|
||||||
if nerr != nil {
|
|
||||||
fmt.Fprintln(ctx.App.Writer, nerr)
|
|
||||||
fmt.Fprintln(ctx.App.Writer)
|
|
||||||
ShowCommandHelp(ctx, c.Name)
|
|
||||||
return nerr
|
|
||||||
}
|
|
||||||
|
|
||||||
context := NewContext(ctx.App, set, ctx)
|
|
||||||
|
|
||||||
if checkCommandCompletions(context, c.Name) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if checkCommandHelp(context, c.Name) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.After != nil {
|
|
||||||
defer func() {
|
|
||||||
afterErr := c.After(context)
|
|
||||||
if afterErr != nil {
|
|
||||||
HandleExitCoder(err)
|
|
||||||
if err != nil {
|
|
||||||
err = NewMultiError(err, afterErr)
|
|
||||||
} else {
|
|
||||||
err = afterErr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Before != nil {
|
|
||||||
err = c.Before(context)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Fprintln(ctx.App.Writer, err)
|
|
||||||
fmt.Fprintln(ctx.App.Writer)
|
|
||||||
ShowCommandHelp(ctx, c.Name)
|
|
||||||
HandleExitCoder(err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Action == nil {
|
|
||||||
c.Action = helpSubcommand.Action
|
|
||||||
}
|
|
||||||
|
|
||||||
context.Command = c
|
|
||||||
err = HandleAction(c.Action, context)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
HandleExitCoder(err)
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Names returns the names including short names and aliases.
|
|
||||||
func (c Command) Names() []string {
|
|
||||||
names := []string{c.Name}
|
|
||||||
|
|
||||||
if c.ShortName != "" {
|
|
||||||
names = append(names, c.ShortName)
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(names, c.Aliases...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// HasName returns true if Command.Name or Command.ShortName matches given name
|
|
||||||
func (c Command) HasName(name string) bool {
|
|
||||||
for _, n := range c.Names() {
|
|
||||||
if n == name {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c Command) startApp(ctx *Context) error {
|
|
||||||
app := NewApp()
|
|
||||||
app.Metadata = ctx.App.Metadata
|
|
||||||
// set the name and usage
|
|
||||||
app.Name = fmt.Sprintf("%s %s", ctx.App.Name, c.Name)
|
|
||||||
if c.HelpName == "" {
|
|
||||||
app.HelpName = c.HelpName
|
|
||||||
} else {
|
|
||||||
app.HelpName = app.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.Description != "" {
|
|
||||||
app.Usage = c.Description
|
|
||||||
} else {
|
|
||||||
app.Usage = c.Usage
|
|
||||||
}
|
|
||||||
|
|
||||||
// set CommandNotFound
|
|
||||||
app.CommandNotFound = ctx.App.CommandNotFound
|
|
||||||
|
|
||||||
// set the flags and commands
|
|
||||||
app.Commands = c.Subcommands
|
|
||||||
app.Flags = c.Flags
|
|
||||||
app.HideHelp = c.HideHelp
|
|
||||||
|
|
||||||
app.Version = ctx.App.Version
|
|
||||||
app.HideVersion = ctx.App.HideVersion
|
|
||||||
app.Compiled = ctx.App.Compiled
|
|
||||||
app.Author = ctx.App.Author
|
|
||||||
app.Email = ctx.App.Email
|
|
||||||
app.Writer = ctx.App.Writer
|
|
||||||
|
|
||||||
app.categories = CommandCategories{}
|
|
||||||
for _, command := range c.Subcommands {
|
|
||||||
app.categories = app.categories.AddCommand(command.Category, command)
|
|
||||||
}
|
|
||||||
|
|
||||||
sort.Sort(app.categories)
|
|
||||||
|
|
||||||
// bash completion
|
|
||||||
app.EnableBashCompletion = ctx.App.EnableBashCompletion
|
|
||||||
if c.BashComplete != nil {
|
|
||||||
app.BashComplete = c.BashComplete
|
|
||||||
}
|
|
||||||
|
|
||||||
// set the actions
|
|
||||||
app.Before = c.Before
|
|
||||||
app.After = c.After
|
|
||||||
if c.Action != nil {
|
|
||||||
app.Action = c.Action
|
|
||||||
} else {
|
|
||||||
app.Action = helpSubcommand.Action
|
|
||||||
}
|
|
||||||
|
|
||||||
for index, cc := range app.Commands {
|
|
||||||
app.Commands[index].commandNamePath = []string{c.Name, cc.Name}
|
|
||||||
}
|
|
||||||
|
|
||||||
return app.RunAsSubcommand(ctx)
|
|
||||||
}
|
|
||||||
|
|
||||||
// VisibleFlags returns a slice of the Flags with Hidden=false
|
|
||||||
func (c Command) VisibleFlags() []Flag {
|
|
||||||
return visibleFlags(c.Flags)
|
|
||||||
}
|
|
@ -1,269 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"flag"
|
|
||||||
"reflect"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
)
|
|
||||||
|
|
||||||
// Context is a type that is passed through to
|
|
||||||
// each Handler action in a cli application. Context
|
|
||||||
// can be used to retrieve context-specific Args and
|
|
||||||
// parsed command-line options.
|
|
||||||
type Context struct {
|
|
||||||
App *App
|
|
||||||
Command Command
|
|
||||||
flagSet *flag.FlagSet
|
|
||||||
setFlags map[string]bool
|
|
||||||
parentContext *Context
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewContext creates a new context. For use in when invoking an App or Command action.
|
|
||||||
func NewContext(app *App, set *flag.FlagSet, parentCtx *Context) *Context {
|
|
||||||
return &Context{App: app, flagSet: set, parentContext: parentCtx}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NumFlags returns the number of flags set
|
|
||||||
func (c *Context) NumFlags() int {
|
|
||||||
return c.flagSet.NFlag()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets a context flag to a value.
|
|
||||||
func (c *Context) Set(name, value string) error {
|
|
||||||
return c.flagSet.Set(name, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalSet sets a context flag to a value on the global flagset
|
|
||||||
func (c *Context) GlobalSet(name, value string) error {
|
|
||||||
return globalContext(c).flagSet.Set(name, value)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsSet determines if the flag was actually set
|
|
||||||
func (c *Context) IsSet(name string) bool {
|
|
||||||
if c.setFlags == nil {
|
|
||||||
c.setFlags = make(map[string]bool)
|
|
||||||
|
|
||||||
c.flagSet.Visit(func(f *flag.Flag) {
|
|
||||||
c.setFlags[f.Name] = true
|
|
||||||
})
|
|
||||||
|
|
||||||
c.flagSet.VisitAll(func(f *flag.Flag) {
|
|
||||||
if _, ok := c.setFlags[f.Name]; ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.setFlags[f.Name] = false
|
|
||||||
})
|
|
||||||
|
|
||||||
// XXX hack to support IsSet for flags with EnvVar
|
|
||||||
//
|
|
||||||
// There isn't an easy way to do this with the current implementation since
|
|
||||||
// whether a flag was set via an environment variable is very difficult to
|
|
||||||
// determine here. Instead, we intend to introduce a backwards incompatible
|
|
||||||
// change in version 2 to add `IsSet` to the Flag interface to push the
|
|
||||||
// responsibility closer to where the information required to determine
|
|
||||||
// whether a flag is set by non-standard means such as environment
|
|
||||||
// variables is avaliable.
|
|
||||||
//
|
|
||||||
// See https://github.com/urfave/cli/issues/294 for additional discussion
|
|
||||||
flags := c.Command.Flags
|
|
||||||
if c.Command.Name == "" { // cannot == Command{} since it contains slice types
|
|
||||||
if c.App != nil {
|
|
||||||
flags = c.App.Flags
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, f := range flags {
|
|
||||||
eachName(f.GetName(), func(name string) {
|
|
||||||
if isSet, ok := c.setFlags[name]; isSet || !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
val := reflect.ValueOf(f)
|
|
||||||
if val.Kind() == reflect.Ptr {
|
|
||||||
val = val.Elem()
|
|
||||||
}
|
|
||||||
|
|
||||||
envVarValue := val.FieldByName("EnvVar")
|
|
||||||
if !envVarValue.IsValid() {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(envVarValue.String(), func(envVar string) {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if _, ok := syscall.Getenv(envVar); ok {
|
|
||||||
c.setFlags[name] = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return c.setFlags[name]
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalIsSet determines if the global flag was actually set
|
|
||||||
func (c *Context) GlobalIsSet(name string) bool {
|
|
||||||
ctx := c
|
|
||||||
if ctx.parentContext != nil {
|
|
||||||
ctx = ctx.parentContext
|
|
||||||
}
|
|
||||||
|
|
||||||
for ; ctx != nil; ctx = ctx.parentContext {
|
|
||||||
if ctx.IsSet(name) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlagNames returns a slice of flag names used in this context.
|
|
||||||
func (c *Context) FlagNames() (names []string) {
|
|
||||||
for _, flag := range c.Command.Flags {
|
|
||||||
name := strings.Split(flag.GetName(), ",")[0]
|
|
||||||
if name == "help" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalFlagNames returns a slice of global flag names used by the app.
|
|
||||||
func (c *Context) GlobalFlagNames() (names []string) {
|
|
||||||
for _, flag := range c.App.Flags {
|
|
||||||
name := strings.Split(flag.GetName(), ",")[0]
|
|
||||||
if name == "help" || name == "version" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
names = append(names, name)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parent returns the parent context, if any
|
|
||||||
func (c *Context) Parent() *Context {
|
|
||||||
return c.parentContext
|
|
||||||
}
|
|
||||||
|
|
||||||
// value returns the value of the flag coressponding to `name`
|
|
||||||
func (c *Context) value(name string) interface{} {
|
|
||||||
return c.flagSet.Lookup(name).Value.(flag.Getter).Get()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Args contains apps console arguments
|
|
||||||
type Args []string
|
|
||||||
|
|
||||||
// Args returns the command line arguments associated with the context.
|
|
||||||
func (c *Context) Args() Args {
|
|
||||||
args := Args(c.flagSet.Args())
|
|
||||||
return args
|
|
||||||
}
|
|
||||||
|
|
||||||
// NArg returns the number of the command line arguments.
|
|
||||||
func (c *Context) NArg() int {
|
|
||||||
return len(c.Args())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the nth argument, or else a blank string
|
|
||||||
func (a Args) Get(n int) string {
|
|
||||||
if len(a) > n {
|
|
||||||
return a[n]
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// First returns the first argument, or else a blank string
|
|
||||||
func (a Args) First() string {
|
|
||||||
return a.Get(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tail returns the rest of the arguments (not the first one)
|
|
||||||
// or else an empty string slice
|
|
||||||
func (a Args) Tail() []string {
|
|
||||||
if len(a) >= 2 {
|
|
||||||
return []string(a)[1:]
|
|
||||||
}
|
|
||||||
return []string{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Present checks if there are any arguments present
|
|
||||||
func (a Args) Present() bool {
|
|
||||||
return len(a) != 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Swap swaps arguments at the given indexes
|
|
||||||
func (a Args) Swap(from, to int) error {
|
|
||||||
if from >= len(a) || to >= len(a) {
|
|
||||||
return errors.New("index out of range")
|
|
||||||
}
|
|
||||||
a[from], a[to] = a[to], a[from]
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func globalContext(ctx *Context) *Context {
|
|
||||||
if ctx == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for {
|
|
||||||
if ctx.parentContext == nil {
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
ctx = ctx.parentContext
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupGlobalFlagSet(name string, ctx *Context) *flag.FlagSet {
|
|
||||||
if ctx.parentContext != nil {
|
|
||||||
ctx = ctx.parentContext
|
|
||||||
}
|
|
||||||
for ; ctx != nil; ctx = ctx.parentContext {
|
|
||||||
if f := ctx.flagSet.Lookup(name); f != nil {
|
|
||||||
return ctx.flagSet
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func copyFlag(name string, ff *flag.Flag, set *flag.FlagSet) {
|
|
||||||
switch ff.Value.(type) {
|
|
||||||
case *StringSlice:
|
|
||||||
default:
|
|
||||||
set.Set(name, ff.Value.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func normalizeFlags(flags []Flag, set *flag.FlagSet) error {
|
|
||||||
visited := make(map[string]bool)
|
|
||||||
set.Visit(func(f *flag.Flag) {
|
|
||||||
visited[f.Name] = true
|
|
||||||
})
|
|
||||||
for _, f := range flags {
|
|
||||||
parts := strings.Split(f.GetName(), ",")
|
|
||||||
if len(parts) == 1 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
var ff *flag.Flag
|
|
||||||
for _, name := range parts {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
if visited[name] {
|
|
||||||
if ff != nil {
|
|
||||||
return errors.New("Cannot use two forms of the same flag: " + name + " " + ff.Name)
|
|
||||||
}
|
|
||||||
ff = set.Lookup(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ff == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, name := range parts {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
if !visited[name] {
|
|
||||||
copyFlag(name, ff, set)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -1,110 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// OsExiter is the function used when the app exits. If not set defaults to os.Exit.
|
|
||||||
var OsExiter = os.Exit
|
|
||||||
|
|
||||||
// ErrWriter is used to write errors to the user. This can be anything
|
|
||||||
// implementing the io.Writer interface and defaults to os.Stderr.
|
|
||||||
var ErrWriter io.Writer = os.Stderr
|
|
||||||
|
|
||||||
// MultiError is an error that wraps multiple errors.
|
|
||||||
type MultiError struct {
|
|
||||||
Errors []error
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewMultiError creates a new MultiError. Pass in one or more errors.
|
|
||||||
func NewMultiError(err ...error) MultiError {
|
|
||||||
return MultiError{Errors: err}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error implements the error interface.
|
|
||||||
func (m MultiError) Error() string {
|
|
||||||
errs := make([]string, len(m.Errors))
|
|
||||||
for i, err := range m.Errors {
|
|
||||||
errs[i] = err.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
return strings.Join(errs, "\n")
|
|
||||||
}
|
|
||||||
|
|
||||||
type ErrorFormatter interface {
|
|
||||||
Format(s fmt.State, verb rune)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExitCoder is the interface checked by `App` and `Command` for a custom exit
|
|
||||||
// code
|
|
||||||
type ExitCoder interface {
|
|
||||||
error
|
|
||||||
ExitCode() int
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExitError fulfills both the builtin `error` interface and `ExitCoder`
|
|
||||||
type ExitError struct {
|
|
||||||
exitCode int
|
|
||||||
message interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewExitError makes a new *ExitError
|
|
||||||
func NewExitError(message interface{}, exitCode int) *ExitError {
|
|
||||||
return &ExitError{
|
|
||||||
exitCode: exitCode,
|
|
||||||
message: message,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error returns the string message, fulfilling the interface required by
|
|
||||||
// `error`
|
|
||||||
func (ee *ExitError) Error() string {
|
|
||||||
return fmt.Sprintf("%v", ee.message)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ExitCode returns the exit code, fulfilling the interface required by
|
|
||||||
// `ExitCoder`
|
|
||||||
func (ee *ExitError) ExitCode() int {
|
|
||||||
return ee.exitCode
|
|
||||||
}
|
|
||||||
|
|
||||||
// HandleExitCoder checks if the error fulfills the ExitCoder interface, and if
|
|
||||||
// so prints the error to stderr (if it is non-empty) and calls OsExiter with the
|
|
||||||
// given exit code. If the given error is a MultiError, then this func is
|
|
||||||
// called on all members of the Errors slice.
|
|
||||||
func HandleExitCoder(err error) {
|
|
||||||
if err == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if exitErr, ok := err.(ExitCoder); ok {
|
|
||||||
if err.Error() != "" {
|
|
||||||
if _, ok := exitErr.(ErrorFormatter); ok {
|
|
||||||
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintln(ErrWriter, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OsExiter(exitErr.ExitCode())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if multiErr, ok := err.(MultiError); ok {
|
|
||||||
for _, merr := range multiErr.Errors {
|
|
||||||
HandleExitCoder(merr)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if err.Error() != "" {
|
|
||||||
if _, ok := err.(ErrorFormatter); ok {
|
|
||||||
fmt.Fprintf(ErrWriter, "%+v\n", err)
|
|
||||||
} else {
|
|
||||||
fmt.Fprintln(ErrWriter, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
OsExiter(1)
|
|
||||||
}
|
|
@ -1,93 +0,0 @@
|
|||||||
[
|
|
||||||
{
|
|
||||||
"name": "Bool",
|
|
||||||
"type": "bool",
|
|
||||||
"value": false,
|
|
||||||
"context_default": "false",
|
|
||||||
"parser": "strconv.ParseBool(f.Value.String())"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "BoolT",
|
|
||||||
"type": "bool",
|
|
||||||
"value": false,
|
|
||||||
"doctail": " that is true by default",
|
|
||||||
"context_default": "false",
|
|
||||||
"parser": "strconv.ParseBool(f.Value.String())"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Duration",
|
|
||||||
"type": "time.Duration",
|
|
||||||
"doctail": " (see https://golang.org/pkg/time/#ParseDuration)",
|
|
||||||
"context_default": "0",
|
|
||||||
"parser": "time.ParseDuration(f.Value.String())"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Float64",
|
|
||||||
"type": "float64",
|
|
||||||
"context_default": "0",
|
|
||||||
"parser": "strconv.ParseFloat(f.Value.String(), 64)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Generic",
|
|
||||||
"type": "Generic",
|
|
||||||
"dest": false,
|
|
||||||
"context_default": "nil",
|
|
||||||
"context_type": "interface{}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Int64",
|
|
||||||
"type": "int64",
|
|
||||||
"context_default": "0",
|
|
||||||
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Int",
|
|
||||||
"type": "int",
|
|
||||||
"context_default": "0",
|
|
||||||
"parser": "strconv.ParseInt(f.Value.String(), 0, 64)",
|
|
||||||
"parser_cast": "int(parsed)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "IntSlice",
|
|
||||||
"type": "*IntSlice",
|
|
||||||
"dest": false,
|
|
||||||
"context_default": "nil",
|
|
||||||
"context_type": "[]int",
|
|
||||||
"parser": "(f.Value.(*IntSlice)).Value(), error(nil)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Int64Slice",
|
|
||||||
"type": "*Int64Slice",
|
|
||||||
"dest": false,
|
|
||||||
"context_default": "nil",
|
|
||||||
"context_type": "[]int64",
|
|
||||||
"parser": "(f.Value.(*Int64Slice)).Value(), error(nil)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "String",
|
|
||||||
"type": "string",
|
|
||||||
"context_default": "\"\"",
|
|
||||||
"parser": "f.Value.String(), error(nil)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "StringSlice",
|
|
||||||
"type": "*StringSlice",
|
|
||||||
"dest": false,
|
|
||||||
"context_default": "nil",
|
|
||||||
"context_type": "[]string",
|
|
||||||
"parser": "(f.Value.(*StringSlice)).Value(), error(nil)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Uint64",
|
|
||||||
"type": "uint64",
|
|
||||||
"context_default": "0",
|
|
||||||
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Uint",
|
|
||||||
"type": "uint",
|
|
||||||
"context_default": "0",
|
|
||||||
"parser": "strconv.ParseUint(f.Value.String(), 0, 64)",
|
|
||||||
"parser_cast": "uint(parsed)"
|
|
||||||
}
|
|
||||||
]
|
|
@ -1,799 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"syscall"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const defaultPlaceholder = "value"
|
|
||||||
|
|
||||||
// BashCompletionFlag enables bash-completion for all commands and subcommands
|
|
||||||
var BashCompletionFlag = BoolFlag{
|
|
||||||
Name: "generate-bash-completion",
|
|
||||||
Hidden: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// VersionFlag prints the version for the application
|
|
||||||
var VersionFlag = BoolFlag{
|
|
||||||
Name: "version, v",
|
|
||||||
Usage: "print the version",
|
|
||||||
}
|
|
||||||
|
|
||||||
// HelpFlag prints the help for all commands and subcommands
|
|
||||||
// Set to the zero value (BoolFlag{}) to disable flag -- keeps subcommand
|
|
||||||
// unless HideHelp is set to true)
|
|
||||||
var HelpFlag = BoolFlag{
|
|
||||||
Name: "help, h",
|
|
||||||
Usage: "show help",
|
|
||||||
}
|
|
||||||
|
|
||||||
// FlagStringer converts a flag definition to a string. This is used by help
|
|
||||||
// to display a flag.
|
|
||||||
var FlagStringer FlagStringFunc = stringifyFlag
|
|
||||||
|
|
||||||
// FlagsByName is a slice of Flag.
|
|
||||||
type FlagsByName []Flag
|
|
||||||
|
|
||||||
func (f FlagsByName) Len() int {
|
|
||||||
return len(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f FlagsByName) Less(i, j int) bool {
|
|
||||||
return f[i].GetName() < f[j].GetName()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f FlagsByName) Swap(i, j int) {
|
|
||||||
f[i], f[j] = f[j], f[i]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Flag is a common interface related to parsing flags in cli.
|
|
||||||
// For more advanced flag parsing techniques, it is recommended that
|
|
||||||
// this interface be implemented.
|
|
||||||
type Flag interface {
|
|
||||||
fmt.Stringer
|
|
||||||
// Apply Flag settings to the given flag set
|
|
||||||
Apply(*flag.FlagSet)
|
|
||||||
GetName() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// errorableFlag is an interface that allows us to return errors during apply
|
|
||||||
// it allows flags defined in this library to return errors in a fashion backwards compatible
|
|
||||||
// TODO remove in v2 and modify the existing Flag interface to return errors
|
|
||||||
type errorableFlag interface {
|
|
||||||
Flag
|
|
||||||
|
|
||||||
applyWithError(*flag.FlagSet) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func flagSet(name string, flags []Flag) (*flag.FlagSet, error) {
|
|
||||||
set := flag.NewFlagSet(name, flag.ContinueOnError)
|
|
||||||
|
|
||||||
for _, f := range flags {
|
|
||||||
//TODO remove in v2 when errorableFlag is removed
|
|
||||||
if f, ok := f.(errorableFlag); ok {
|
|
||||||
if err := f.applyWithError(set); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
f.Apply(set)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return set, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func eachName(longName string, fn func(string)) {
|
|
||||||
parts := strings.Split(longName, ",")
|
|
||||||
for _, name := range parts {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
fn(name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic is a generic parseable type identified by a specific flag
|
|
||||||
type Generic interface {
|
|
||||||
Set(value string) error
|
|
||||||
String() string
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply takes the flagset and calls Set on the generic flag with the value
|
|
||||||
// provided by the user for parsing by the flag
|
|
||||||
// Ignores parsing errors
|
|
||||||
func (f GenericFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError takes the flagset and calls Set on the generic flag with the value
|
|
||||||
// provided by the user for parsing by the flag
|
|
||||||
func (f GenericFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
val := f.Value
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
if err := val.Set(envVal); err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
set.Var(f.Value, name, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice is an opaque type for []string to satisfy flag.Value and flag.Getter
|
|
||||||
type StringSlice []string
|
|
||||||
|
|
||||||
// Set appends the string value to the list of values
|
|
||||||
func (f *StringSlice) Set(value string) error {
|
|
||||||
*f = append(*f, value)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value (for usage defaults)
|
|
||||||
func (f *StringSlice) String() string {
|
|
||||||
return fmt.Sprintf("%s", *f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the slice of strings set by this flag
|
|
||||||
func (f *StringSlice) Value() []string {
|
|
||||||
return *f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the slice of strings set by this flag
|
|
||||||
func (f *StringSlice) Get() interface{} {
|
|
||||||
return *f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f StringSliceFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f StringSliceFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
newVal := &StringSlice{}
|
|
||||||
for _, s := range strings.Split(envVal, ",") {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
if err := newVal.Set(s); err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as string value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.Value = newVal
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Value == nil {
|
|
||||||
f.Value = &StringSlice{}
|
|
||||||
}
|
|
||||||
set.Var(f.Value, name, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSlice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
|
||||||
type IntSlice []int
|
|
||||||
|
|
||||||
// Set parses the value into an integer and appends it to the list of values
|
|
||||||
func (f *IntSlice) Set(value string) error {
|
|
||||||
tmp, err := strconv.Atoi(value)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*f = append(*f, tmp)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value (for usage defaults)
|
|
||||||
func (f *IntSlice) String() string {
|
|
||||||
return fmt.Sprintf("%#v", *f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the slice of ints set by this flag
|
|
||||||
func (f *IntSlice) Value() []int {
|
|
||||||
return *f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the slice of ints set by this flag
|
|
||||||
func (f *IntSlice) Get() interface{} {
|
|
||||||
return *f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f IntSliceFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f IntSliceFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
newVal := &IntSlice{}
|
|
||||||
for _, s := range strings.Split(envVal, ",") {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
if err := newVal.Set(s); err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as int slice value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.Value = newVal
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Value == nil {
|
|
||||||
f.Value = &IntSlice{}
|
|
||||||
}
|
|
||||||
set.Var(f.Value, name, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64Slice is an opaque type for []int to satisfy flag.Value and flag.Getter
|
|
||||||
type Int64Slice []int64
|
|
||||||
|
|
||||||
// Set parses the value into an integer and appends it to the list of values
|
|
||||||
func (f *Int64Slice) Set(value string) error {
|
|
||||||
tmp, err := strconv.ParseInt(value, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
*f = append(*f, tmp)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value (for usage defaults)
|
|
||||||
func (f *Int64Slice) String() string {
|
|
||||||
return fmt.Sprintf("%#v", *f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Value returns the slice of ints set by this flag
|
|
||||||
func (f *Int64Slice) Value() []int64 {
|
|
||||||
return *f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the slice of ints set by this flag
|
|
||||||
func (f *Int64Slice) Get() interface{} {
|
|
||||||
return *f
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f Int64SliceFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f Int64SliceFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
newVal := &Int64Slice{}
|
|
||||||
for _, s := range strings.Split(envVal, ",") {
|
|
||||||
s = strings.TrimSpace(s)
|
|
||||||
if err := newVal.Set(s); err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as int64 slice value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
f.Value = newVal
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Value == nil {
|
|
||||||
f.Value = &Int64Slice{}
|
|
||||||
}
|
|
||||||
set.Var(f.Value, name, f.Usage)
|
|
||||||
})
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f BoolFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f BoolFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
val := false
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
if envVal == "" {
|
|
||||||
val = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
envValBool, err := strconv.ParseBool(envVal)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
val = envValBool
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.BoolVar(f.Destination, name, val, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Bool(name, val, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f BoolTFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f BoolTFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
val := true
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
if envVal == "" {
|
|
||||||
val = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
envValBool, err := strconv.ParseBool(envVal)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as bool value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
val = envValBool
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.BoolVar(f.Destination, name, val, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Bool(name, val, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f StringFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f StringFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
f.Value = envVal
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.StringVar(f.Destination, name, f.Value, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.String(name, f.Value, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f IntFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f IntFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
f.Value = int(envValInt)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.IntVar(f.Destination, name, f.Value, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Int(name, f.Value, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f Int64Flag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f Int64Flag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
envValInt, err := strconv.ParseInt(envVal, 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as int value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Value = envValInt
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.Int64Var(f.Destination, name, f.Value, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Int64(name, f.Value, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f UintFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f UintFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as uint value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Value = uint(envValInt)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.UintVar(f.Destination, name, f.Value, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Uint(name, f.Value, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f Uint64Flag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f Uint64Flag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
envValInt, err := strconv.ParseUint(envVal, 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as uint64 value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Value = uint64(envValInt)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.Uint64Var(f.Destination, name, f.Value, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Uint64(name, f.Value, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f DurationFlag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f DurationFlag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
envValDuration, err := time.ParseDuration(envVal)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as duration for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Value = envValDuration
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.DurationVar(f.Destination, name, f.Value, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Duration(name, f.Value, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Apply populates the flag given the flag set and environment
|
|
||||||
// Ignores errors
|
|
||||||
func (f Float64Flag) Apply(set *flag.FlagSet) {
|
|
||||||
f.applyWithError(set)
|
|
||||||
}
|
|
||||||
|
|
||||||
// applyWithError populates the flag given the flag set and environment
|
|
||||||
func (f Float64Flag) applyWithError(set *flag.FlagSet) error {
|
|
||||||
if f.EnvVar != "" {
|
|
||||||
for _, envVar := range strings.Split(f.EnvVar, ",") {
|
|
||||||
envVar = strings.TrimSpace(envVar)
|
|
||||||
if envVal, ok := syscall.Getenv(envVar); ok {
|
|
||||||
envValFloat, err := strconv.ParseFloat(envVal, 10)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("could not parse %s as float64 value for flag %s: %s", envVal, f.Name, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
f.Value = float64(envValFloat)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eachName(f.Name, func(name string) {
|
|
||||||
if f.Destination != nil {
|
|
||||||
set.Float64Var(f.Destination, name, f.Value, f.Usage)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
set.Float64(name, f.Value, f.Usage)
|
|
||||||
})
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func visibleFlags(fl []Flag) []Flag {
|
|
||||||
visible := []Flag{}
|
|
||||||
for _, flag := range fl {
|
|
||||||
if !flagValue(flag).FieldByName("Hidden").Bool() {
|
|
||||||
visible = append(visible, flag)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return visible
|
|
||||||
}
|
|
||||||
|
|
||||||
func prefixFor(name string) (prefix string) {
|
|
||||||
if len(name) == 1 {
|
|
||||||
prefix = "-"
|
|
||||||
} else {
|
|
||||||
prefix = "--"
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Returns the placeholder, if any, and the unquoted usage string.
|
|
||||||
func unquoteUsage(usage string) (string, string) {
|
|
||||||
for i := 0; i < len(usage); i++ {
|
|
||||||
if usage[i] == '`' {
|
|
||||||
for j := i + 1; j < len(usage); j++ {
|
|
||||||
if usage[j] == '`' {
|
|
||||||
name := usage[i+1 : j]
|
|
||||||
usage = usage[:i] + name + usage[j+1:]
|
|
||||||
return name, usage
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return "", usage
|
|
||||||
}
|
|
||||||
|
|
||||||
func prefixedNames(fullName, placeholder string) string {
|
|
||||||
var prefixed string
|
|
||||||
parts := strings.Split(fullName, ",")
|
|
||||||
for i, name := range parts {
|
|
||||||
name = strings.Trim(name, " ")
|
|
||||||
prefixed += prefixFor(name) + name
|
|
||||||
if placeholder != "" {
|
|
||||||
prefixed += " " + placeholder
|
|
||||||
}
|
|
||||||
if i < len(parts)-1 {
|
|
||||||
prefixed += ", "
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return prefixed
|
|
||||||
}
|
|
||||||
|
|
||||||
func withEnvHint(envVar, str string) string {
|
|
||||||
envText := ""
|
|
||||||
if envVar != "" {
|
|
||||||
prefix := "$"
|
|
||||||
suffix := ""
|
|
||||||
sep := ", $"
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
prefix = "%"
|
|
||||||
suffix = "%"
|
|
||||||
sep = "%, %"
|
|
||||||
}
|
|
||||||
envText = fmt.Sprintf(" [%s%s%s]", prefix, strings.Join(strings.Split(envVar, ","), sep), suffix)
|
|
||||||
}
|
|
||||||
return str + envText
|
|
||||||
}
|
|
||||||
|
|
||||||
func flagValue(f Flag) reflect.Value {
|
|
||||||
fv := reflect.ValueOf(f)
|
|
||||||
for fv.Kind() == reflect.Ptr {
|
|
||||||
fv = reflect.Indirect(fv)
|
|
||||||
}
|
|
||||||
return fv
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringifyFlag(f Flag) string {
|
|
||||||
fv := flagValue(f)
|
|
||||||
|
|
||||||
switch f.(type) {
|
|
||||||
case IntSliceFlag:
|
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
|
||||||
stringifyIntSliceFlag(f.(IntSliceFlag)))
|
|
||||||
case Int64SliceFlag:
|
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
|
||||||
stringifyInt64SliceFlag(f.(Int64SliceFlag)))
|
|
||||||
case StringSliceFlag:
|
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
|
||||||
stringifyStringSliceFlag(f.(StringSliceFlag)))
|
|
||||||
}
|
|
||||||
|
|
||||||
placeholder, usage := unquoteUsage(fv.FieldByName("Usage").String())
|
|
||||||
|
|
||||||
needsPlaceholder := false
|
|
||||||
defaultValueString := ""
|
|
||||||
val := fv.FieldByName("Value")
|
|
||||||
|
|
||||||
if val.IsValid() {
|
|
||||||
needsPlaceholder = true
|
|
||||||
defaultValueString = fmt.Sprintf(" (default: %v)", val.Interface())
|
|
||||||
|
|
||||||
if val.Kind() == reflect.String && val.String() != "" {
|
|
||||||
defaultValueString = fmt.Sprintf(" (default: %q)", val.String())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if defaultValueString == " (default: )" {
|
|
||||||
defaultValueString = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
if needsPlaceholder && placeholder == "" {
|
|
||||||
placeholder = defaultPlaceholder
|
|
||||||
}
|
|
||||||
|
|
||||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultValueString))
|
|
||||||
|
|
||||||
return withEnvHint(fv.FieldByName("EnvVar").String(),
|
|
||||||
fmt.Sprintf("%s\t%s", prefixedNames(fv.FieldByName("Name").String(), placeholder), usageWithDefault))
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringifyIntSliceFlag(f IntSliceFlag) string {
|
|
||||||
defaultVals := []string{}
|
|
||||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
|
||||||
for _, i := range f.Value.Value() {
|
|
||||||
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringifyInt64SliceFlag(f Int64SliceFlag) string {
|
|
||||||
defaultVals := []string{}
|
|
||||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
|
||||||
for _, i := range f.Value.Value() {
|
|
||||||
defaultVals = append(defaultVals, fmt.Sprintf("%d", i))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringifyStringSliceFlag(f StringSliceFlag) string {
|
|
||||||
defaultVals := []string{}
|
|
||||||
if f.Value != nil && len(f.Value.Value()) > 0 {
|
|
||||||
for _, s := range f.Value.Value() {
|
|
||||||
if len(s) > 0 {
|
|
||||||
defaultVals = append(defaultVals, fmt.Sprintf("%q", s))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return stringifySliceFlag(f.Usage, f.Name, defaultVals)
|
|
||||||
}
|
|
||||||
|
|
||||||
func stringifySliceFlag(usage, name string, defaultVals []string) string {
|
|
||||||
placeholder, usage := unquoteUsage(usage)
|
|
||||||
if placeholder == "" {
|
|
||||||
placeholder = defaultPlaceholder
|
|
||||||
}
|
|
||||||
|
|
||||||
defaultVal := ""
|
|
||||||
if len(defaultVals) > 0 {
|
|
||||||
defaultVal = fmt.Sprintf(" (default: %s)", strings.Join(defaultVals, ", "))
|
|
||||||
}
|
|
||||||
|
|
||||||
usageWithDefault := strings.TrimSpace(fmt.Sprintf("%s%s", usage, defaultVal))
|
|
||||||
return fmt.Sprintf("%s\t%s", prefixedNames(name, placeholder), usageWithDefault)
|
|
||||||
}
|
|
@ -1,627 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"flag"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WARNING: This file is generated!
|
|
||||||
|
|
||||||
// BoolFlag is a flag with type bool
|
|
||||||
type BoolFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Destination *bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f BoolFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f BoolFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Bool looks up the value of a local BoolFlag, returns
|
|
||||||
// false if not found
|
|
||||||
func (c *Context) Bool(name string) bool {
|
|
||||||
return lookupBool(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalBool looks up the value of a global BoolFlag, returns
|
|
||||||
// false if not found
|
|
||||||
func (c *Context) GlobalBool(name string) bool {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupBool(name, fs)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupBool(name string, set *flag.FlagSet) bool {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := strconv.ParseBool(f.Value.String())
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolTFlag is a flag with type bool that is true by default
|
|
||||||
type BoolTFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Destination *bool
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f BoolTFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f BoolTFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// BoolT looks up the value of a local BoolTFlag, returns
|
|
||||||
// false if not found
|
|
||||||
func (c *Context) BoolT(name string) bool {
|
|
||||||
return lookupBoolT(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalBoolT looks up the value of a global BoolTFlag, returns
|
|
||||||
// false if not found
|
|
||||||
func (c *Context) GlobalBoolT(name string) bool {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupBoolT(name, fs)
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupBoolT(name string, set *flag.FlagSet) bool {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := strconv.ParseBool(f.Value.String())
|
|
||||||
if err != nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// DurationFlag is a flag with type time.Duration (see https://golang.org/pkg/time/#ParseDuration)
|
|
||||||
type DurationFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value time.Duration
|
|
||||||
Destination *time.Duration
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f DurationFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f DurationFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Duration looks up the value of a local DurationFlag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) Duration(name string) time.Duration {
|
|
||||||
return lookupDuration(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalDuration looks up the value of a global DurationFlag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) GlobalDuration(name string) time.Duration {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupDuration(name, fs)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupDuration(name string, set *flag.FlagSet) time.Duration {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := time.ParseDuration(f.Value.String())
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64Flag is a flag with type float64
|
|
||||||
type Float64Flag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value float64
|
|
||||||
Destination *float64
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f Float64Flag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f Float64Flag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Float64 looks up the value of a local Float64Flag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) Float64(name string) float64 {
|
|
||||||
return lookupFloat64(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalFloat64 looks up the value of a global Float64Flag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) GlobalFloat64(name string) float64 {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupFloat64(name, fs)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupFloat64(name string, set *flag.FlagSet) float64 {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := strconv.ParseFloat(f.Value.String(), 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenericFlag is a flag with type Generic
|
|
||||||
type GenericFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value Generic
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f GenericFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f GenericFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Generic looks up the value of a local GenericFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) Generic(name string) interface{} {
|
|
||||||
return lookupGeneric(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalGeneric looks up the value of a global GenericFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) GlobalGeneric(name string) interface{} {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupGeneric(name, fs)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupGeneric(name string, set *flag.FlagSet) interface{} {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := f.Value, error(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64Flag is a flag with type int64
|
|
||||||
type Int64Flag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value int64
|
|
||||||
Destination *int64
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f Int64Flag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f Int64Flag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64 looks up the value of a local Int64Flag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) Int64(name string) int64 {
|
|
||||||
return lookupInt64(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalInt64 looks up the value of a global Int64Flag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) GlobalInt64(name string) int64 {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupInt64(name, fs)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupInt64(name string, set *flag.FlagSet) int64 {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntFlag is a flag with type int
|
|
||||||
type IntFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value int
|
|
||||||
Destination *int
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f IntFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f IntFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int looks up the value of a local IntFlag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) Int(name string) int {
|
|
||||||
return lookupInt(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalInt looks up the value of a global IntFlag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) GlobalInt(name string) int {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupInt(name, fs)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupInt(name string, set *flag.FlagSet) int {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := strconv.ParseInt(f.Value.String(), 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return int(parsed)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSliceFlag is a flag with type *IntSlice
|
|
||||||
type IntSliceFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value *IntSlice
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f IntSliceFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f IntSliceFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// IntSlice looks up the value of a local IntSliceFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) IntSlice(name string) []int {
|
|
||||||
return lookupIntSlice(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalIntSlice looks up the value of a global IntSliceFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) GlobalIntSlice(name string) []int {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupIntSlice(name, fs)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupIntSlice(name string, set *flag.FlagSet) []int {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := (f.Value.(*IntSlice)).Value(), error(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64SliceFlag is a flag with type *Int64Slice
|
|
||||||
type Int64SliceFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value *Int64Slice
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f Int64SliceFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f Int64SliceFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Int64Slice looks up the value of a local Int64SliceFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) Int64Slice(name string) []int64 {
|
|
||||||
return lookupInt64Slice(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalInt64Slice looks up the value of a global Int64SliceFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) GlobalInt64Slice(name string) []int64 {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupInt64Slice(name, fs)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupInt64Slice(name string, set *flag.FlagSet) []int64 {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := (f.Value.(*Int64Slice)).Value(), error(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringFlag is a flag with type string
|
|
||||||
type StringFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value string
|
|
||||||
Destination *string
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f StringFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f StringFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// String looks up the value of a local StringFlag, returns
|
|
||||||
// "" if not found
|
|
||||||
func (c *Context) String(name string) string {
|
|
||||||
return lookupString(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalString looks up the value of a global StringFlag, returns
|
|
||||||
// "" if not found
|
|
||||||
func (c *Context) GlobalString(name string) string {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupString(name, fs)
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupString(name string, set *flag.FlagSet) string {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := f.Value.String(), error(nil)
|
|
||||||
if err != nil {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSliceFlag is a flag with type *StringSlice
|
|
||||||
type StringSliceFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value *StringSlice
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f StringSliceFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f StringSliceFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// StringSlice looks up the value of a local StringSliceFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) StringSlice(name string) []string {
|
|
||||||
return lookupStringSlice(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalStringSlice looks up the value of a global StringSliceFlag, returns
|
|
||||||
// nil if not found
|
|
||||||
func (c *Context) GlobalStringSlice(name string) []string {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupStringSlice(name, fs)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupStringSlice(name string, set *flag.FlagSet) []string {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := (f.Value.(*StringSlice)).Value(), error(nil)
|
|
||||||
if err != nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64Flag is a flag with type uint64
|
|
||||||
type Uint64Flag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value uint64
|
|
||||||
Destination *uint64
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f Uint64Flag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f Uint64Flag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint64 looks up the value of a local Uint64Flag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) Uint64(name string) uint64 {
|
|
||||||
return lookupUint64(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalUint64 looks up the value of a global Uint64Flag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) GlobalUint64(name string) uint64 {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupUint64(name, fs)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupUint64(name string, set *flag.FlagSet) uint64 {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return parsed
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
// UintFlag is a flag with type uint
|
|
||||||
type UintFlag struct {
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
Value uint
|
|
||||||
Destination *uint
|
|
||||||
}
|
|
||||||
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f UintFlag) String() string {
|
|
||||||
return FlagStringer(f)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f UintFlag) GetName() string {
|
|
||||||
return f.Name
|
|
||||||
}
|
|
||||||
|
|
||||||
// Uint looks up the value of a local UintFlag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) Uint(name string) uint {
|
|
||||||
return lookupUint(name, c.flagSet)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GlobalUint looks up the value of a global UintFlag, returns
|
|
||||||
// 0 if not found
|
|
||||||
func (c *Context) GlobalUint(name string) uint {
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {
|
|
||||||
return lookupUint(name, fs)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func lookupUint(name string, set *flag.FlagSet) uint {
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {
|
|
||||||
parsed, err := strconv.ParseUint(f.Value.String(), 0, 64)
|
|
||||||
if err != nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
return uint(parsed)
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
@ -1,28 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
// BashCompleteFunc is an action to execute when the bash-completion flag is set
|
|
||||||
type BashCompleteFunc func(*Context)
|
|
||||||
|
|
||||||
// BeforeFunc is an action to execute before any subcommands are run, but after
|
|
||||||
// the context is ready if a non-nil error is returned, no subcommands are run
|
|
||||||
type BeforeFunc func(*Context) error
|
|
||||||
|
|
||||||
// AfterFunc is an action to execute after any subcommands are run, but after the
|
|
||||||
// subcommand has finished it is run even if Action() panics
|
|
||||||
type AfterFunc func(*Context) error
|
|
||||||
|
|
||||||
// ActionFunc is the action to execute when no subcommands are specified
|
|
||||||
type ActionFunc func(*Context) error
|
|
||||||
|
|
||||||
// CommandNotFoundFunc is executed if the proper command cannot be found
|
|
||||||
type CommandNotFoundFunc func(*Context, string)
|
|
||||||
|
|
||||||
// OnUsageErrorFunc is executed if an usage error occurs. This is useful for displaying
|
|
||||||
// customized usage error messages. This function is able to replace the
|
|
||||||
// original error messages. If this function is not set, the "Incorrect usage"
|
|
||||||
// is displayed and the execution is interrupted.
|
|
||||||
type OnUsageErrorFunc func(context *Context, err error, isSubcommand bool) error
|
|
||||||
|
|
||||||
// FlagStringFunc is used by the help generation to display a flag, which is
|
|
||||||
// expected to be a single line.
|
|
||||||
type FlagStringFunc func(Flag) string
|
|
@ -1,248 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
"""
|
|
||||||
The flag types that ship with the cli library have many things in common, and
|
|
||||||
so we can take advantage of the `go generate` command to create much of the
|
|
||||||
source code from a list of definitions. These definitions attempt to cover
|
|
||||||
the parts that vary between flag types, and should evolve as needed.
|
|
||||||
|
|
||||||
An example of the minimum definition needed is:
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "SomeType",
|
|
||||||
"type": "sometype",
|
|
||||||
"context_default": "nil"
|
|
||||||
}
|
|
||||||
|
|
||||||
In this example, the code generated for the `cli` package will include a type
|
|
||||||
named `SomeTypeFlag` that is expected to wrap a value of type `sometype`.
|
|
||||||
Fetching values by name via `*cli.Context` will default to a value of `nil`.
|
|
||||||
|
|
||||||
A more complete, albeit somewhat redundant, example showing all available
|
|
||||||
definition keys is:
|
|
||||||
|
|
||||||
{
|
|
||||||
"name": "VeryMuchType",
|
|
||||||
"type": "*VeryMuchType",
|
|
||||||
"value": true,
|
|
||||||
"dest": false,
|
|
||||||
"doctail": " which really only wraps a []float64, oh well!",
|
|
||||||
"context_type": "[]float64",
|
|
||||||
"context_default": "nil",
|
|
||||||
"parser": "parseVeryMuchType(f.Value.String())",
|
|
||||||
"parser_cast": "[]float64(parsed)"
|
|
||||||
}
|
|
||||||
|
|
||||||
The meaning of each field is as follows:
|
|
||||||
|
|
||||||
name (string) - The type "name", which will be suffixed with
|
|
||||||
`Flag` when generating the type definition
|
|
||||||
for `cli` and the wrapper type for `altsrc`
|
|
||||||
type (string) - The type that the generated `Flag` type for `cli`
|
|
||||||
is expected to "contain" as its `.Value` member
|
|
||||||
value (bool) - Should the generated `cli` type have a `Value`
|
|
||||||
member?
|
|
||||||
dest (bool) - Should the generated `cli` type support a
|
|
||||||
destination pointer?
|
|
||||||
doctail (string) - Additional docs for the `cli` flag type comment
|
|
||||||
context_type (string) - The literal type used in the `*cli.Context`
|
|
||||||
reader func signature
|
|
||||||
context_default (string) - The literal value used as the default by the
|
|
||||||
`*cli.Context` reader funcs when no value is
|
|
||||||
present
|
|
||||||
parser (string) - Literal code used to parse the flag `f`,
|
|
||||||
expected to have a return signature of
|
|
||||||
(value, error)
|
|
||||||
parser_cast (string) - Literal code used to cast the `parsed` value
|
|
||||||
returned from the `parser` code
|
|
||||||
"""
|
|
||||||
|
|
||||||
from __future__ import print_function, unicode_literals
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import json
|
|
||||||
import os
|
|
||||||
import subprocess
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
import textwrap
|
|
||||||
|
|
||||||
|
|
||||||
class _FancyFormatter(argparse.ArgumentDefaultsHelpFormatter,
|
|
||||||
argparse.RawDescriptionHelpFormatter):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def main(sysargs=sys.argv[:]):
|
|
||||||
parser = argparse.ArgumentParser(
|
|
||||||
description='Generate flag type code!',
|
|
||||||
formatter_class=_FancyFormatter)
|
|
||||||
parser.add_argument(
|
|
||||||
'package',
|
|
||||||
type=str, default='cli', choices=_WRITEFUNCS.keys(),
|
|
||||||
help='Package for which flag types will be generated'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'-i', '--in-json',
|
|
||||||
type=argparse.FileType('r'),
|
|
||||||
default=sys.stdin,
|
|
||||||
help='Input JSON file which defines each type to be generated'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'-o', '--out-go',
|
|
||||||
type=argparse.FileType('w'),
|
|
||||||
default=sys.stdout,
|
|
||||||
help='Output file/stream to which generated source will be written'
|
|
||||||
)
|
|
||||||
parser.epilog = __doc__
|
|
||||||
|
|
||||||
args = parser.parse_args(sysargs[1:])
|
|
||||||
_generate_flag_types(_WRITEFUNCS[args.package], args.out_go, args.in_json)
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def _generate_flag_types(writefunc, output_go, input_json):
|
|
||||||
types = json.load(input_json)
|
|
||||||
|
|
||||||
tmp = tempfile.NamedTemporaryFile(suffix='.go', delete=False)
|
|
||||||
writefunc(tmp, types)
|
|
||||||
tmp.close()
|
|
||||||
|
|
||||||
new_content = subprocess.check_output(
|
|
||||||
['goimports', tmp.name]
|
|
||||||
).decode('utf-8')
|
|
||||||
|
|
||||||
print(new_content, file=output_go, end='')
|
|
||||||
output_go.flush()
|
|
||||||
os.remove(tmp.name)
|
|
||||||
|
|
||||||
|
|
||||||
def _set_typedef_defaults(typedef):
|
|
||||||
typedef.setdefault('doctail', '')
|
|
||||||
typedef.setdefault('context_type', typedef['type'])
|
|
||||||
typedef.setdefault('dest', True)
|
|
||||||
typedef.setdefault('value', True)
|
|
||||||
typedef.setdefault('parser', 'f.Value, error(nil)')
|
|
||||||
typedef.setdefault('parser_cast', 'parsed')
|
|
||||||
|
|
||||||
|
|
||||||
def _write_cli_flag_types(outfile, types):
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
package cli
|
|
||||||
|
|
||||||
// WARNING: This file is generated!
|
|
||||||
|
|
||||||
""")
|
|
||||||
|
|
||||||
for typedef in types:
|
|
||||||
_set_typedef_defaults(typedef)
|
|
||||||
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
// {name}Flag is a flag with type {type}{doctail}
|
|
||||||
type {name}Flag struct {{
|
|
||||||
Name string
|
|
||||||
Usage string
|
|
||||||
EnvVar string
|
|
||||||
Hidden bool
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
if typedef['value']:
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
Value {type}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
if typedef['dest']:
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
Destination *{type}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
_fwrite(outfile, "\n}\n\n")
|
|
||||||
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
// String returns a readable representation of this value
|
|
||||||
// (for usage defaults)
|
|
||||||
func (f {name}Flag) String() string {{
|
|
||||||
return FlagStringer(f)
|
|
||||||
}}
|
|
||||||
|
|
||||||
// GetName returns the name of the flag
|
|
||||||
func (f {name}Flag) GetName() string {{
|
|
||||||
return f.Name
|
|
||||||
}}
|
|
||||||
|
|
||||||
// {name} looks up the value of a local {name}Flag, returns
|
|
||||||
// {context_default} if not found
|
|
||||||
func (c *Context) {name}(name string) {context_type} {{
|
|
||||||
return lookup{name}(name, c.flagSet)
|
|
||||||
}}
|
|
||||||
|
|
||||||
// Global{name} looks up the value of a global {name}Flag, returns
|
|
||||||
// {context_default} if not found
|
|
||||||
func (c *Context) Global{name}(name string) {context_type} {{
|
|
||||||
if fs := lookupGlobalFlagSet(name, c); fs != nil {{
|
|
||||||
return lookup{name}(name, fs)
|
|
||||||
}}
|
|
||||||
return {context_default}
|
|
||||||
}}
|
|
||||||
|
|
||||||
func lookup{name}(name string, set *flag.FlagSet) {context_type} {{
|
|
||||||
f := set.Lookup(name)
|
|
||||||
if f != nil {{
|
|
||||||
parsed, err := {parser}
|
|
||||||
if err != nil {{
|
|
||||||
return {context_default}
|
|
||||||
}}
|
|
||||||
return {parser_cast}
|
|
||||||
}}
|
|
||||||
return {context_default}
|
|
||||||
}}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
|
|
||||||
def _write_altsrc_flag_types(outfile, types):
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
package altsrc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"gopkg.in/urfave/cli.v1"
|
|
||||||
)
|
|
||||||
|
|
||||||
// WARNING: This file is generated!
|
|
||||||
|
|
||||||
""")
|
|
||||||
|
|
||||||
for typedef in types:
|
|
||||||
_set_typedef_defaults(typedef)
|
|
||||||
|
|
||||||
_fwrite(outfile, """\
|
|
||||||
// {name}Flag is the flag type that wraps cli.{name}Flag to allow
|
|
||||||
// for other values to be specified
|
|
||||||
type {name}Flag struct {{
|
|
||||||
cli.{name}Flag
|
|
||||||
set *flag.FlagSet
|
|
||||||
}}
|
|
||||||
|
|
||||||
// New{name}Flag creates a new {name}Flag
|
|
||||||
func New{name}Flag(fl cli.{name}Flag) *{name}Flag {{
|
|
||||||
return &{name}Flag{{{name}Flag: fl, set: nil}}
|
|
||||||
}}
|
|
||||||
|
|
||||||
// Apply saves the flagSet for later usage calls, then calls the
|
|
||||||
// wrapped {name}Flag.Apply
|
|
||||||
func (f *{name}Flag) Apply(set *flag.FlagSet) {{
|
|
||||||
f.set = set
|
|
||||||
f.{name}Flag.Apply(set)
|
|
||||||
}}
|
|
||||||
""".format(**typedef))
|
|
||||||
|
|
||||||
|
|
||||||
def _fwrite(outfile, text):
|
|
||||||
print(textwrap.dedent(text), end='', file=outfile)
|
|
||||||
|
|
||||||
|
|
||||||
_WRITEFUNCS = {
|
|
||||||
'cli': _write_cli_flag_types,
|
|
||||||
'altsrc': _write_altsrc_flag_types
|
|
||||||
}
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
@ -1,271 +0,0 @@
|
|||||||
package cli
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"os"
|
|
||||||
"strings"
|
|
||||||
"text/tabwriter"
|
|
||||||
"text/template"
|
|
||||||
)
|
|
||||||
|
|
||||||
// AppHelpTemplate is the text template for the Default help topic.
|
|
||||||
// cli.go uses text/template to render templates. You can
|
|
||||||
// render custom help text by setting this variable.
|
|
||||||
var AppHelpTemplate = `NAME:
|
|
||||||
{{.Name}}{{if .Usage}} - {{.Usage}}{{end}}
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
{{if .UsageText}}{{.UsageText}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
|
|
||||||
|
|
||||||
VERSION:
|
|
||||||
{{.Version}}{{end}}{{end}}{{if .Description}}
|
|
||||||
|
|
||||||
DESCRIPTION:
|
|
||||||
{{.Description}}{{end}}{{if len .Authors}}
|
|
||||||
|
|
||||||
AUTHOR{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
|
|
||||||
{{range $index, $author := .Authors}}{{if $index}}
|
|
||||||
{{end}}{{$author}}{{end}}{{end}}{{if .VisibleCommands}}
|
|
||||||
|
|
||||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
|
||||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
|
||||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{end}}{{end}}{{if .VisibleFlags}}
|
|
||||||
|
|
||||||
GLOBAL OPTIONS:
|
|
||||||
{{range $index, $option := .VisibleFlags}}{{if $index}}
|
|
||||||
{{end}}{{$option}}{{end}}{{end}}{{if .Copyright}}
|
|
||||||
|
|
||||||
COPYRIGHT:
|
|
||||||
{{.Copyright}}{{end}}
|
|
||||||
`
|
|
||||||
|
|
||||||
// CommandHelpTemplate is the text template for the command help topic.
|
|
||||||
// cli.go uses text/template to render templates. You can
|
|
||||||
// render custom help text by setting this variable.
|
|
||||||
var CommandHelpTemplate = `NAME:
|
|
||||||
{{.HelpName}} - {{.Usage}}
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
{{.HelpName}}{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{if .Category}}
|
|
||||||
|
|
||||||
CATEGORY:
|
|
||||||
{{.Category}}{{end}}{{if .Description}}
|
|
||||||
|
|
||||||
DESCRIPTION:
|
|
||||||
{{.Description}}{{end}}{{if .VisibleFlags}}
|
|
||||||
|
|
||||||
OPTIONS:
|
|
||||||
{{range .VisibleFlags}}{{.}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
`
|
|
||||||
|
|
||||||
// SubcommandHelpTemplate is the text template for the subcommand help topic.
|
|
||||||
// cli.go uses text/template to render templates. You can
|
|
||||||
// render custom help text by setting this variable.
|
|
||||||
var SubcommandHelpTemplate = `NAME:
|
|
||||||
{{.HelpName}} - {{.Usage}}
|
|
||||||
|
|
||||||
USAGE:
|
|
||||||
{{.HelpName}} command{{if .VisibleFlags}} [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}
|
|
||||||
|
|
||||||
COMMANDS:{{range .VisibleCategories}}{{if .Name}}
|
|
||||||
{{.Name}}:{{end}}{{range .VisibleCommands}}
|
|
||||||
{{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}
|
|
||||||
{{end}}{{if .VisibleFlags}}
|
|
||||||
OPTIONS:
|
|
||||||
{{range .VisibleFlags}}{{.}}
|
|
||||||
{{end}}{{end}}
|
|
||||||
`
|
|
||||||
|
|
||||||
var helpCommand = Command{
|
|
||||||
Name: "help",
|
|
||||||
Aliases: []string{"h"},
|
|
||||||
Usage: "Shows a list of commands or help for one command",
|
|
||||||
ArgsUsage: "[command]",
|
|
||||||
Action: func(c *Context) error {
|
|
||||||
args := c.Args()
|
|
||||||
if args.Present() {
|
|
||||||
return ShowCommandHelp(c, args.First())
|
|
||||||
}
|
|
||||||
|
|
||||||
ShowAppHelp(c)
|
|
||||||
return nil
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
var helpSubcommand = Command{
|
|
||||||
Name: "help",
|
|
||||||
Aliases: []string{"h"},
|
|
||||||
Usage: "Shows a list of commands or help for one command",
|
|
||||||
ArgsUsage: "[command]",
|
|
||||||
Action: func(c *Context) error {
|
|
||||||
args := c.Args()
|
|
||||||
if args.Present() {
|
|
||||||
return ShowCommandHelp(c, args.First())
|
|
||||||
}
|
|
||||||
|
|
||||||
return ShowSubcommandHelp(c)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prints help for the App or Command
|
|
||||||
type helpPrinter func(w io.Writer, templ string, data interface{})
|
|
||||||
|
|
||||||
// HelpPrinter is a function that writes the help output. If not set a default
|
|
||||||
// is used. The function signature is:
|
|
||||||
// func(w io.Writer, templ string, data interface{})
|
|
||||||
var HelpPrinter helpPrinter = printHelp
|
|
||||||
|
|
||||||
// VersionPrinter prints the version for the App
|
|
||||||
var VersionPrinter = printVersion
|
|
||||||
|
|
||||||
// ShowAppHelp is an action that displays the help.
|
|
||||||
func ShowAppHelp(c *Context) error {
|
|
||||||
HelpPrinter(c.App.Writer, AppHelpTemplate, c.App)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// DefaultAppComplete prints the list of subcommands as the default app completion method
|
|
||||||
func DefaultAppComplete(c *Context) {
|
|
||||||
for _, command := range c.App.Commands {
|
|
||||||
if command.Hidden {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, name := range command.Names() {
|
|
||||||
fmt.Fprintln(c.App.Writer, name)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShowCommandHelp prints help for the given command
|
|
||||||
func ShowCommandHelp(ctx *Context, command string) error {
|
|
||||||
// show the subcommand help for a command with subcommands
|
|
||||||
if command == "" {
|
|
||||||
HelpPrinter(ctx.App.Writer, SubcommandHelpTemplate, ctx.App)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, c := range ctx.App.Commands {
|
|
||||||
if c.HasName(command) {
|
|
||||||
HelpPrinter(ctx.App.Writer, CommandHelpTemplate, c)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.App.CommandNotFound == nil {
|
|
||||||
return NewExitError(fmt.Sprintf("No help topic for '%v'", command), 3)
|
|
||||||
}
|
|
||||||
|
|
||||||
ctx.App.CommandNotFound(ctx, command)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShowSubcommandHelp prints help for the given subcommand
|
|
||||||
func ShowSubcommandHelp(c *Context) error {
|
|
||||||
return ShowCommandHelp(c, c.Command.Name)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShowVersion prints the version number of the App
|
|
||||||
func ShowVersion(c *Context) {
|
|
||||||
VersionPrinter(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
func printVersion(c *Context) {
|
|
||||||
fmt.Fprintf(c.App.Writer, "%v version %v\n", c.App.Name, c.App.Version)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShowCompletions prints the lists of commands within a given context
|
|
||||||
func ShowCompletions(c *Context) {
|
|
||||||
a := c.App
|
|
||||||
if a != nil && a.BashComplete != nil {
|
|
||||||
a.BashComplete(c)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShowCommandCompletions prints the custom completions for a given command
|
|
||||||
func ShowCommandCompletions(ctx *Context, command string) {
|
|
||||||
c := ctx.App.Command(command)
|
|
||||||
if c != nil && c.BashComplete != nil {
|
|
||||||
c.BashComplete(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func printHelp(out io.Writer, templ string, data interface{}) {
|
|
||||||
funcMap := template.FuncMap{
|
|
||||||
"join": strings.Join,
|
|
||||||
}
|
|
||||||
|
|
||||||
w := tabwriter.NewWriter(out, 1, 8, 2, ' ', 0)
|
|
||||||
t := template.Must(template.New("help").Funcs(funcMap).Parse(templ))
|
|
||||||
err := t.Execute(w, data)
|
|
||||||
if err != nil {
|
|
||||||
// If the writer is closed, t.Execute will fail, and there's nothing
|
|
||||||
// we can do to recover.
|
|
||||||
if os.Getenv("CLI_TEMPLATE_ERROR_DEBUG") != "" {
|
|
||||||
fmt.Fprintf(ErrWriter, "CLI TEMPLATE ERROR: %#v\n", err)
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
w.Flush()
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkVersion(c *Context) bool {
|
|
||||||
found := false
|
|
||||||
if VersionFlag.Name != "" {
|
|
||||||
eachName(VersionFlag.Name, func(name string) {
|
|
||||||
if c.GlobalBool(name) || c.Bool(name) {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkHelp(c *Context) bool {
|
|
||||||
found := false
|
|
||||||
if HelpFlag.Name != "" {
|
|
||||||
eachName(HelpFlag.Name, func(name string) {
|
|
||||||
if c.GlobalBool(name) || c.Bool(name) {
|
|
||||||
found = true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return found
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkCommandHelp(c *Context, name string) bool {
|
|
||||||
if c.Bool("h") || c.Bool("help") {
|
|
||||||
ShowCommandHelp(c, name)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkSubcommandHelp(c *Context) bool {
|
|
||||||
if c.Bool("h") || c.Bool("help") {
|
|
||||||
ShowSubcommandHelp(c)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkCompletions(c *Context) bool {
|
|
||||||
if (c.GlobalBool(BashCompletionFlag.Name) || c.Bool(BashCompletionFlag.Name)) && c.App.EnableBashCompletion {
|
|
||||||
ShowCompletions(c)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkCommandCompletions(c *Context, name string) bool {
|
|
||||||
if c.Bool(BashCompletionFlag.Name) && c.App.EnableBashCompletion {
|
|
||||||
ShowCommandCompletions(c, name)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
|
@ -1,122 +0,0 @@
|
|||||||
#!/usr/bin/env python
|
|
||||||
from __future__ import print_function
|
|
||||||
|
|
||||||
import argparse
|
|
||||||
import os
|
|
||||||
import sys
|
|
||||||
import tempfile
|
|
||||||
|
|
||||||
from subprocess import check_call, check_output
|
|
||||||
|
|
||||||
|
|
||||||
PACKAGE_NAME = os.environ.get(
|
|
||||||
'CLI_PACKAGE_NAME', 'github.com/urfave/cli'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def main(sysargs=sys.argv[:]):
|
|
||||||
targets = {
|
|
||||||
'vet': _vet,
|
|
||||||
'test': _test,
|
|
||||||
'gfmrun': _gfmrun,
|
|
||||||
'toc': _toc,
|
|
||||||
'gen': _gen,
|
|
||||||
}
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser()
|
|
||||||
parser.add_argument(
|
|
||||||
'target', nargs='?', choices=tuple(targets.keys()), default='test'
|
|
||||||
)
|
|
||||||
args = parser.parse_args(sysargs[1:])
|
|
||||||
|
|
||||||
targets[args.target]()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
|
|
||||||
def _test():
|
|
||||||
if check_output('go version'.split()).split()[2] < 'go1.2':
|
|
||||||
_run('go test -v .')
|
|
||||||
return
|
|
||||||
|
|
||||||
coverprofiles = []
|
|
||||||
for subpackage in ['', 'altsrc']:
|
|
||||||
coverprofile = 'cli.coverprofile'
|
|
||||||
if subpackage != '':
|
|
||||||
coverprofile = '{}.coverprofile'.format(subpackage)
|
|
||||||
|
|
||||||
coverprofiles.append(coverprofile)
|
|
||||||
|
|
||||||
_run('go test -v'.split() + [
|
|
||||||
'-coverprofile={}'.format(coverprofile),
|
|
||||||
('{}/{}'.format(PACKAGE_NAME, subpackage)).rstrip('/')
|
|
||||||
])
|
|
||||||
|
|
||||||
combined_name = _combine_coverprofiles(coverprofiles)
|
|
||||||
_run('go tool cover -func={}'.format(combined_name))
|
|
||||||
os.remove(combined_name)
|
|
||||||
|
|
||||||
|
|
||||||
def _gfmrun():
|
|
||||||
go_version = check_output('go version'.split()).split()[2]
|
|
||||||
if go_version < 'go1.3':
|
|
||||||
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
|
|
||||||
return
|
|
||||||
_run(['gfmrun', '-c', str(_gfmrun_count()), '-s', 'README.md'])
|
|
||||||
|
|
||||||
|
|
||||||
def _vet():
|
|
||||||
_run('go vet ./...')
|
|
||||||
|
|
||||||
|
|
||||||
def _toc():
|
|
||||||
_run('node_modules/.bin/markdown-toc -i README.md')
|
|
||||||
_run('git diff --exit-code')
|
|
||||||
|
|
||||||
|
|
||||||
def _gen():
|
|
||||||
go_version = check_output('go version'.split()).split()[2]
|
|
||||||
if go_version < 'go1.5':
|
|
||||||
print('runtests: skip on {}'.format(go_version), file=sys.stderr)
|
|
||||||
return
|
|
||||||
|
|
||||||
_run('go generate ./...')
|
|
||||||
_run('git diff --exit-code')
|
|
||||||
|
|
||||||
|
|
||||||
def _run(command):
|
|
||||||
if hasattr(command, 'split'):
|
|
||||||
command = command.split()
|
|
||||||
print('runtests: {}'.format(' '.join(command)), file=sys.stderr)
|
|
||||||
check_call(command)
|
|
||||||
|
|
||||||
|
|
||||||
def _gfmrun_count():
|
|
||||||
with open('README.md') as infile:
|
|
||||||
lines = infile.read().splitlines()
|
|
||||||
return len(filter(_is_go_runnable, lines))
|
|
||||||
|
|
||||||
|
|
||||||
def _is_go_runnable(line):
|
|
||||||
return line.startswith('package main')
|
|
||||||
|
|
||||||
|
|
||||||
def _combine_coverprofiles(coverprofiles):
|
|
||||||
combined = tempfile.NamedTemporaryFile(
|
|
||||||
suffix='.coverprofile', delete=False
|
|
||||||
)
|
|
||||||
combined.write('mode: set\n')
|
|
||||||
|
|
||||||
for coverprofile in coverprofiles:
|
|
||||||
with open(coverprofile, 'r') as infile:
|
|
||||||
for line in infile.readlines():
|
|
||||||
if not line.startswith('mode: '):
|
|
||||||
combined.write(line)
|
|
||||||
|
|
||||||
combined.flush()
|
|
||||||
name = combined.name
|
|
||||||
combined.close()
|
|
||||||
return name
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
sys.exit(main())
|
|
@ -1,31 +0,0 @@
|
|||||||
{
|
|
||||||
"comment": "",
|
|
||||||
"ignore": "test",
|
|
||||||
"package": [
|
|
||||||
{
|
|
||||||
"checksumSHA1": "Txg0JnycL8J24q8M+3bMuQPikR4=",
|
|
||||||
"path": "github.com/dnsimple/dnsimple-go/dnsimple",
|
|
||||||
"revision": "c5e18853275d3022c35e13fd9600048320f1d84f",
|
|
||||||
"revisionTime": "2016-11-22T10:27:37Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"checksumSHA1": "yyAzHoiVLu+xywYI2BDyRq6sOqE=",
|
|
||||||
"path": "github.com/google/go-querystring/query",
|
|
||||||
"revision": "9235644dd9e52eeae6fa48efd539fdc351a0af53",
|
|
||||||
"revisionTime": "2016-03-11T01:20:12Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"checksumSHA1": "ynJSWoF6v+3zMnh9R0QmmG6iGV8=",
|
|
||||||
"path": "github.com/pkg/errors",
|
|
||||||
"revision": "248dadf4e9068a0b3e79f02ed0a610d935de5302",
|
|
||||||
"revisionTime": "2016-10-29T09:36:37Z"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"checksumSHA1": "Y2hFNyygY4Zx41H2phH/rEJgRRo=",
|
|
||||||
"path": "github.com/urfave/cli",
|
|
||||||
"revision": "b4f4786f378c0c1d3336b5bb798094b166edf5a9",
|
|
||||||
"revisionTime": "2016-11-13T23:35:18Z"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"rootPath": "git.xbudex.com/buddy/update-dns"
|
|
||||||
}
|
|
Loading…
Reference in New Issue