diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 280a423a1..abee8ac57 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -14,9 +14,9 @@ jobs: with: go-version: "1.25.x" - name: golangci-lint - uses: golangci/golangci-lint-action@v6 + uses: golangci/golangci-lint-action@v9 with: - version: v1.64.8 + version: v2.6.2 test: runs-on: ubuntu-latest diff --git a/.golangci.yml b/.golangci.yml index 68a8e953b..913bddb87 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -1,30 +1,37 @@ -run: - # timeout for analysis, e.g. 30s, 5m, default is 1m - timeout: 5m +version: "2" linters: enable: - #- golint - #- interfacer - - unconvert - #- dupl - goconst - - gofmt - misspell - - unparam - nakedret - prealloc - revive - #- gosec -linters-settings: - misspell: - locale: US - revive: + - unconvert + - unparam + settings: + misspell: + locale: US + revive: + rules: + - name: redundant-build-tag + exclusions: + generated: lax rules: - - name: redundant-build-tag + - path: (.+)\.go$ + text: G104 + paths: + - third_party$ + - builtin$ + - examples$ issues: - max-same-issues: 0 max-issues-per-linter: 0 - exclude-use-default: false - exclude: - # gosec: Duplicated errcheck checks - - G104 + max-same-issues: 0 +formatters: + enable: + - gofmt + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/database/cassandra/cassandra.go b/database/cassandra/cassandra.go index 815427d12..159ad6c80 100644 --- a/database/cassandra/cassandra.go +++ b/database/cassandra/cassandra.go @@ -336,7 +336,7 @@ func parseConsistency(consistencyStr string) (consistency gocql.Consistency, err var ok bool err, ok = r.(error) if !ok { - err = fmt.Errorf("Failed to parse consistency \"%s\": %v", consistencyStr, r) + err = fmt.Errorf("failed to parse consistency \"%s\": %v", consistencyStr, r) } } }() diff --git a/database/clickhouse/clickhouse.go b/database/clickhouse/clickhouse.go index 819af0664..fa85aa189 100644 --- a/database/clickhouse/clickhouse.go +++ b/database/clickhouse/clickhouse.go @@ -307,5 +307,5 @@ func quoteIdentifier(name string) string { if end > -1 { name = name[:end] } - return `"` + strings.Replace(name, `"`, `""`, -1) + `"` + return `"` + strings.ReplaceAll(name, `"`, `""`) + `"` } diff --git a/database/mysql/mysql.go b/database/mysql/mysql.go index 61a59d295..7efb79bc4 100644 --- a/database/mysql/mysql.go +++ b/database/mysql/mysql.go @@ -34,7 +34,7 @@ var ( ErrNilConfig = fmt.Errorf("no config") ErrNoDatabaseName = fmt.Errorf("no database name") ErrAppendPEM = fmt.Errorf("failed to append PEM") - ErrTLSCertKeyConfig = fmt.Errorf("To use TLS client authentication, both x-tls-cert and x-tls-key must not be empty") + ErrTLSCertKeyConfig = fmt.Errorf("to use TLS client authentication, both x-tls-cert and x-tls-key must not be empty") ) type Config struct { diff --git a/database/pgx/pgx.go b/database/pgx/pgx.go index c84e70dfc..e97f15e9f 100644 --- a/database/pgx/pgx.go +++ b/database/pgx/pgx.go @@ -181,7 +181,7 @@ func (p *Postgres) Open(url string) (database.Driver, error) { if s := purl.Query().Get("x-migrations-table-quoted"); len(s) > 0 { migrationsTableQuoted, err = strconv.ParseBool(s) if err != nil { - return nil, fmt.Errorf("Unable to parse option x-migrations-table-quoted: %w", err) + return nil, fmt.Errorf("unable to parse option x-migrations-table-quoted: %w", err) } } if (len(migrationsTable) > 0) && (migrationsTableQuoted) && ((migrationsTable[0] != '"') || (migrationsTable[len(migrationsTable)-1] != '"')) { @@ -212,7 +212,7 @@ func (p *Postgres) Open(url string) (database.Driver, error) { if s := purl.Query().Get("x-multi-statement"); len(s) > 0 { multiStatementEnabled, err = strconv.ParseBool(s) if err != nil { - return nil, fmt.Errorf("Unable to parse option x-multi-statement: %w", err) + return nil, fmt.Errorf("unable to parse option x-multi-statement: %w", err) } } @@ -412,7 +412,7 @@ func (p *Postgres) runStatement(statement []byte) error { func computeLineFromPos(s string, pos int) (line uint, col uint, ok bool) { // replace crlf with lf - s = strings.Replace(s, "\r\n", "\n", -1) + s = strings.ReplaceAll(s, "\r\n", "\n") // pg docs: pos uses index 1 for the first character, and positions are measured in characters not bytes runes := []rune(s) if pos > len(runes) { @@ -613,5 +613,5 @@ func quoteIdentifier(name string) string { if end > -1 { name = name[:end] } - return `"` + strings.Replace(name, `"`, `""`, -1) + `"` + return `"` + strings.ReplaceAll(name, `"`, `""`) + `"` } diff --git a/database/pgx/pgx_test.go b/database/pgx/pgx_test.go index 018aa7cdb..d86caeb36 100644 --- a/database/pgx/pgx_test.go +++ b/database/pgx/pgx_test.go @@ -755,10 +755,10 @@ func Test_computeLineFromPos(t *testing.T) { t.Run(name, func(t *testing.T) { input := tc.input if crlf { - input = strings.Replace(input, "\n", "\r\n", -1) + input = strings.ReplaceAll(input, "\n", "\r\n") } if nonASCII { - input = strings.Replace(input, "FROM", "FRÖM", -1) + input = strings.ReplaceAll(input, "FROM", "FRÖM") } gotLine, gotCol, gotOK := computeLineFromPos(input, tc.pos) diff --git a/database/pgx/v5/pgx.go b/database/pgx/v5/pgx.go index ee1960fe5..ef5f05674 100644 --- a/database/pgx/v5/pgx.go +++ b/database/pgx/v5/pgx.go @@ -157,7 +157,7 @@ func (p *Postgres) Open(url string) (database.Driver, error) { if s := purl.Query().Get("x-migrations-table-quoted"); len(s) > 0 { migrationsTableQuoted, err = strconv.ParseBool(s) if err != nil { - return nil, fmt.Errorf("Unable to parse option x-migrations-table-quoted: %w", err) + return nil, fmt.Errorf("unable to parse option x-migrations-table-quoted: %w", err) } } if (len(migrationsTable) > 0) && (migrationsTableQuoted) && ((migrationsTable[0] != '"') || (migrationsTable[len(migrationsTable)-1] != '"')) { @@ -188,7 +188,7 @@ func (p *Postgres) Open(url string) (database.Driver, error) { if s := purl.Query().Get("x-multi-statement"); len(s) > 0 { multiStatementEnabled, err = strconv.ParseBool(s) if err != nil { - return nil, fmt.Errorf("Unable to parse option x-multi-statement: %w", err) + return nil, fmt.Errorf("unable to parse option x-multi-statement: %w", err) } } @@ -303,7 +303,7 @@ func (p *Postgres) runStatement(statement []byte) error { func computeLineFromPos(s string, pos int) (line uint, col uint, ok bool) { // replace crlf with lf - s = strings.Replace(s, "\r\n", "\n", -1) + s = strings.ReplaceAll(s, "\r\n", "\n") // pg docs: pos uses index 1 for the first character, and positions are measured in characters not bytes runes := []rune(s) if pos > len(runes) { @@ -476,5 +476,5 @@ func quoteIdentifier(name string) string { if end > -1 { name = name[:end] } - return `"` + strings.Replace(name, `"`, `""`, -1) + `"` + return `"` + strings.ReplaceAll(name, `"`, `""`) + `"` } diff --git a/database/pgx/v5/pgx_test.go b/database/pgx/v5/pgx_test.go index 52cf60830..9a8652768 100644 --- a/database/pgx/v5/pgx_test.go +++ b/database/pgx/v5/pgx_test.go @@ -730,10 +730,10 @@ func Test_computeLineFromPos(t *testing.T) { t.Run(name, func(t *testing.T) { input := tc.input if crlf { - input = strings.Replace(input, "\n", "\r\n", -1) + input = strings.ReplaceAll(input, "\n", "\r\n") } if nonASCII { - input = strings.Replace(input, "FROM", "FRÖM", -1) + input = strings.ReplaceAll(input, "FROM", "FRÖM") } gotLine, gotCol, gotOK := computeLineFromPos(input, tc.pos) diff --git a/database/postgres/postgres.go b/database/postgres/postgres.go index 7a0f546dd..ed96fe63e 100644 --- a/database/postgres/postgres.go +++ b/database/postgres/postgres.go @@ -165,7 +165,7 @@ func (p *Postgres) Open(url string) (database.Driver, error) { if s := purl.Query().Get("x-migrations-table-quoted"); len(s) > 0 { migrationsTableQuoted, err = strconv.ParseBool(s) if err != nil { - return nil, fmt.Errorf("Unable to parse option x-migrations-table-quoted: %w", err) + return nil, fmt.Errorf("unable to parse option x-migrations-table-quoted: %w", err) } } if (len(migrationsTable) > 0) && (migrationsTableQuoted) && ((migrationsTable[0] != '"') || (migrationsTable[len(migrationsTable)-1] != '"')) { @@ -196,7 +196,7 @@ func (p *Postgres) Open(url string) (database.Driver, error) { if s := purl.Query().Get("x-multi-statement"); len(s) > 0 { multiStatementEnabled, err = strconv.ParseBool(s) if err != nil { - return nil, fmt.Errorf("Unable to parse option x-multi-statement: %w", err) + return nil, fmt.Errorf("unable to parse option x-multi-statement: %w", err) } } @@ -319,7 +319,7 @@ func (p *Postgres) runStatement(statement []byte) error { func computeLineFromPos(s string, pos int) (line uint, col uint, ok bool) { // replace crlf with lf - s = strings.Replace(s, "\r\n", "\n", -1) + s = strings.ReplaceAll(s, "\r\n", "\n") // pg docs: pos uses index 1 for the first character, and positions are measured in characters not bytes runes := []rune(s) if pos > len(runes) { diff --git a/database/postgres/postgres_test.go b/database/postgres/postgres_test.go index 0eea47e94..3a49c50ab 100644 --- a/database/postgres/postgres_test.go +++ b/database/postgres/postgres_test.go @@ -798,10 +798,10 @@ func Test_computeLineFromPos(t *testing.T) { t.Run(name, func(t *testing.T) { input := tc.input if crlf { - input = strings.Replace(input, "\n", "\r\n", -1) + input = strings.ReplaceAll(input, "\n", "\r\n") } if nonASCII { - input = strings.Replace(input, "FROM", "FRÖM", -1) + input = strings.ReplaceAll(input, "FROM", "FRÖM") } gotLine, gotCol, gotOK := computeLineFromPos(input, tc.pos) diff --git a/database/redshift/redshift.go b/database/redshift/redshift.go index d8b91db88..7f6af164f 100644 --- a/database/redshift/redshift.go +++ b/database/redshift/redshift.go @@ -174,7 +174,7 @@ func (p *Redshift) Run(migration io.Reader) error { func computeLineFromPos(s string, pos int) (line uint, col uint, ok bool) { // replace crlf with lf - s = strings.Replace(s, "\r\n", "\n", -1) + s = strings.ReplaceAll(s, "\r\n", "\n") // pg docs: pos uses index 1 for the first character, and positions are measured in characters not bytes runes := []rune(s) if pos > len(runes) { diff --git a/database/redshift/redshift_test.go b/database/redshift/redshift_test.go index 9ee5cbe64..030d87b6e 100644 --- a/database/redshift/redshift_test.go +++ b/database/redshift/redshift_test.go @@ -378,10 +378,10 @@ func Test_computeLineFromPos(t *testing.T) { t.Run(name, func(t *testing.T) { input := tc.input if crlf { - input = strings.Replace(input, "\n", "\r\n", -1) + input = strings.ReplaceAll(input, "\n", "\r\n") } if nonASCII { - input = strings.Replace(input, "FROM", "FRÖM", -1) + input = strings.ReplaceAll(input, "FROM", "FRÖM") } gotLine, gotCol, gotOK := computeLineFromPos(input, tc.pos) diff --git a/database/snowflake/snowflake.go b/database/snowflake/snowflake.go index 8611e18e6..ed9132004 100644 --- a/database/snowflake/snowflake.go +++ b/database/snowflake/snowflake.go @@ -206,7 +206,7 @@ func (p *Snowflake) Run(migration io.Reader) error { func computeLineFromPos(s string, pos int) (line uint, col uint, ok bool) { // replace crlf with lf - s = strings.Replace(s, "\r\n", "\n", -1) + s = strings.ReplaceAll(s, "\r\n", "\n") // pg docs: pos uses index 1 for the first character, and positions are measured in characters not bytes runes := []rune(s) if pos > len(runes) { diff --git a/database/sqlserver/sqlserver.go b/database/sqlserver/sqlserver.go index 9af3a113e..c77bde1f8 100644 --- a/database/sqlserver/sqlserver.go +++ b/database/sqlserver/sqlserver.go @@ -29,7 +29,7 @@ var ( ErrNoDatabaseName = fmt.Errorf("no database name") ErrNoSchema = fmt.Errorf("no schema") ErrDatabaseDirty = fmt.Errorf("database is dirty") - ErrMultipleAuthOptionsPassed = fmt.Errorf("both password and useMsi=true were passed.") + ErrMultipleAuthOptionsPassed = fmt.Errorf("both password and useMsi=true were passed") ) var lockErrorMap = map[int]string{ diff --git a/database/testing/testing.go b/database/testing/testing.go index e735d2b46..bac85c6c0 100644 --- a/database/testing/testing.go +++ b/database/testing/testing.go @@ -50,7 +50,7 @@ func TestLockAndUnlock(t *testing.T, d database.Driver) { case <-done: return case <-timeout: - errs <- fmt.Errorf("Timeout after 15 seconds. Looks like a deadlock in Lock/UnLock.\n%#v", d) + errs <- fmt.Errorf("timeout after 15 seconds, looks like a deadlock in Lock/UnLock\n%#v", d) return } } diff --git a/internal/cli/commands.go b/internal/cli/commands.go index 7adec2f84..e37ca313e 100644 --- a/internal/cli/commands.go +++ b/internal/cli/commands.go @@ -15,9 +15,9 @@ import ( ) var ( - errInvalidSequenceWidth = errors.New("Digits must be positive") - errIncompatibleSeqAndFormat = errors.New("The seq and format options are mutually exclusive") - errInvalidTimeFormat = errors.New("Time format may not be empty") + errInvalidSequenceWidth = errors.New("digits must be positive") + errIncompatibleSeqAndFormat = errors.New("the seq and format options are mutually exclusive") + errInvalidTimeFormat = errors.New("time format may not be empty") ) func nextSeqVersion(matches []string, seqDigits int) (string, error) { @@ -33,7 +33,7 @@ func nextSeqVersion(matches []string, seqDigits int) (string, error) { idx := strings.Index(matchSeqStr, "_") if idx < 1 { // Using 1 instead of 0 since there should be at least 1 digit - return "", fmt.Errorf("Malformed migration filename: %s", filename) + return "", fmt.Errorf("malformed migration filename: %s", filename) } var err error @@ -50,7 +50,7 @@ func nextSeqVersion(matches []string, seqDigits int) (string, error) { version := fmt.Sprintf("%0[2]*[1]d", nextSeq, seqDigits) if len(version) > seqDigits { - return "", fmt.Errorf("Next sequence number %s too large. At most %d digits are allowed", version, seqDigits) + return "", fmt.Errorf("next sequence number %s too large, at most %d digits are allowed", version, seqDigits) } return version, nil diff --git a/internal/cli/commands_test.go b/internal/cli/commands_test.go index e89a690f5..798e2df77 100644 --- a/internal/cli/commands_test.go +++ b/internal/cli/commands_test.go @@ -84,17 +84,17 @@ func (s *CreateCmdSuite) TestNextSeqVersion() { }{ {"Bad digits", []string{}, 0, "", errInvalidSequenceWidth}, {"Single digit initialize", []string{}, 1, "1", nil}, - {"Single digit malformed", []string{"bad"}, 1, "", errors.New("Malformed migration filename: bad")}, + {"Single digit malformed", []string{"bad"}, 1, "", errors.New("malformed migration filename: bad")}, {"Single digit no int", []string{"bad_bad"}, 1, "", errors.New(`strconv.ParseUint: parsing "bad": invalid syntax`)}, {"Single digit negative seq", []string{"-5_test"}, 1, "", errors.New(`strconv.ParseUint: parsing "-5": invalid syntax`)}, {"Single digit increment", []string{"3_test", "4_test"}, 1, "5", nil}, - {"Single digit overflow", []string{"9_test"}, 1, "", errors.New("Next sequence number 10 too large. At most 1 digits are allowed")}, + {"Single digit overflow", []string{"9_test"}, 1, "", errors.New("next sequence number 10 too large, at most 1 digits are allowed")}, {"Zero-pad initialize", []string{}, 6, "000001", nil}, - {"Zero-pad malformed", []string{"bad"}, 6, "", errors.New("Malformed migration filename: bad")}, + {"Zero-pad malformed", []string{"bad"}, 6, "", errors.New("malformed migration filename: bad")}, {"Zero-pad no int", []string{"bad_bad"}, 6, "", errors.New(`strconv.ParseUint: parsing "bad": invalid syntax`)}, {"Zero-pad negative seq", []string{"-000005_test"}, 6, "", errors.New(`strconv.ParseUint: parsing "-000005": invalid syntax`)}, {"Zero-pad increment", []string{"000003_test", "000004_test"}, 6, "000005", nil}, - {"Zero-pad overflow", []string{"999999_test"}, 6, "", errors.New("Next sequence number 1000000 too large. At most 6 digits are allowed")}, + {"Zero-pad overflow", []string{"999999_test"}, 6, "", errors.New("next sequence number 1000000 too large, at most 6 digits are allowed")}, {"dir absolute path", []string{"/migrationDir/000001_test"}, 6, "000002", nil}, {"dir relative path", []string{"migrationDir/000001_test"}, 6, "000002", nil}, {"dir dot prefix", []string{"./migrationDir/000001_test"}, 6, "000002", nil}, @@ -188,11 +188,11 @@ func (s *CreateCmdSuite) TestCreateCmd() { {"seq init dir double dot relative trailing slash", []string{"subdir"}, "subdir", nil, []string{"subdir/0001_name.up.sql", "subdir/0001_name.down.sql"}, nil, "../subdir/", ts, defaultTimeFormat, true, 4, "sql", "name"}, {"seq init dir maze", []string{"subdir"}, "subdir", nil, []string{"0001_name.up.sql", "0001_name.down.sql"}, nil, "..//subdir/./.././/subdir/..", ts, defaultTimeFormat, true, 4, "sql", "name"}, {"seq width invalid", nil, "", nil, nil, errInvalidSequenceWidth, ".", ts, defaultTimeFormat, true, 0, "sql", "name"}, - {"seq malformed", nil, "", []string{"bad.sql"}, []string{"bad.sql"}, errors.New("Malformed migration filename: bad.sql"), ".", ts, defaultTimeFormat, true, 4, "sql", "name"}, + {"seq malformed", nil, "", []string{"bad.sql"}, []string{"bad.sql"}, errors.New("malformed migration filename: bad.sql"), ".", ts, defaultTimeFormat, true, 4, "sql", "name"}, {"seq not int", nil, "", []string{"bad_bad.sql"}, []string{"bad_bad.sql"}, errors.New(`strconv.ParseUint: parsing "bad": invalid syntax`), ".", ts, defaultTimeFormat, true, 4, "sql", "name"}, {"seq negative", nil, "", []string{"-5_negative.sql"}, []string{"-5_negative.sql"}, errors.New(`strconv.ParseUint: parsing "-5": invalid syntax`), ".", ts, defaultTimeFormat, true, 4, "sql", "name"}, {"seq increment", nil, "", []string{"3_three.sql", "4_four.sql"}, []string{"3_three.sql", "4_four.sql", "0005_five.up.sql", "0005_five.down.sql"}, nil, ".", ts, defaultTimeFormat, true, 4, "sql", "five"}, - {"seq overflow", nil, "", []string{"9_nine.sql"}, []string{"9_nine.sql"}, errors.New(`Next sequence number 10 too large. At most 1 digits are allowed`), ".", ts, defaultTimeFormat, true, 1, "sql", "ten"}, + {"seq overflow", nil, "", []string{"9_nine.sql"}, []string{"9_nine.sql"}, errors.New(`next sequence number 10 too large, at most 1 digits are allowed`), ".", ts, defaultTimeFormat, true, 1, "sql", "ten"}, {"time empty format", nil, "", nil, nil, errInvalidTimeFormat, ".", ts, "", false, 0, "sql", "name"}, {"time unix", nil, "", nil, []string{tsUnixStr + "_name.up.sql", tsUnixStr + "_name.down.sql"}, nil, ".", ts, "unix", false, 0, "sql", "name"}, {"time unixNano", nil, "", nil, []string{tsUnixNanoStr + "_name.up.sql", tsUnixNanoStr + "_name.down.sql"}, nil, ".", ts, "unixNano", false, 0, "sql", "name"}, diff --git a/source/gitlab/gitlab.go b/source/gitlab/gitlab.go index 674062e27..694a7fb06 100644 --- a/source/gitlab/gitlab.go +++ b/source/gitlab/gitlab.go @@ -130,7 +130,7 @@ func (g *Gitlab) readDirectory() error { if response.CurrentPage >= response.TotalPages { break } - g.listOptions.ListOptions.Page = response.NextPage + g.listOptions.Page = response.NextPage } for i := range nodes { diff --git a/source/httpfs/driver.go b/source/httpfs/driver.go index e0cdbaa00..96b4a8d5c 100644 --- a/source/httpfs/driver.go +++ b/source/httpfs/driver.go @@ -27,5 +27,5 @@ func New(fs http.FileSystem, path string) (source.Driver, error) { // Open completes the implementetion of source.Driver interface. Other methods // are implemented by the embedded PartialDriver struct. func (d *driver) Open(url string) (source.Driver, error) { - return nil, errors.New("Open() cannot be called on the httpfs passthrough driver") + return nil, errors.New("open() cannot be called on the httpfs passthrough driver") } diff --git a/source/iofs/iofs.go b/source/iofs/iofs.go index a9dc7c4b1..4d5733c34 100644 --- a/source/iofs/iofs.go +++ b/source/iofs/iofs.go @@ -29,7 +29,7 @@ func New(fsys fs.FS, path string) (source.Driver, error) { // Open is part of source.Driver interface implementation. // Open cannot be called on the iofs passthrough driver. func (d *driver) Open(url string) (source.Driver, error) { - return nil, errors.New("Open() cannot be called on the iofs passthrough driver") + return nil, errors.New("open() cannot be called on the iofs passthrough driver") } // PartialDriver is a helper service for creating new source drivers working with diff --git a/testing/docker.go b/testing/docker.go index 96e20227d..35193e747 100644 --- a/testing/docker.go +++ b/testing/docker.go @@ -69,7 +69,7 @@ type DockerContainer struct { func (d *DockerContainer) PullImage() (err error) { if d == nil { - return errors.New("Cannot pull image on a nil *DockerContainer") + return errors.New("cannot pull image on a nil *DockerContainer") } d.t.Logf("Docker: Pull image %v", d.ImageName) r, err := d.client.ImagePull(context.Background(), d.ImageName, dockerimage.PullOptions{}) @@ -98,7 +98,7 @@ func (d *DockerContainer) PullImage() (err error) { func (d *DockerContainer) Start() error { if d == nil { - return errors.New("Cannot start a nil *DockerContainer") + return errors.New("cannot start a nil *DockerContainer") } containerName := fmt.Sprintf("migrate_test_%s", pseudoRandStr(10)) @@ -146,7 +146,7 @@ func (d *DockerContainer) KeepForDebugging() { func (d *DockerContainer) Remove() error { if d == nil { - return errors.New("Cannot remove a nil *DockerContainer") + return errors.New("cannot remove a nil *DockerContainer") } if d.keepForDebugging { @@ -169,7 +169,7 @@ func (d *DockerContainer) Remove() error { func (d *DockerContainer) Inspect() error { if d == nil { - return errors.New("Cannot inspect a nil *DockerContainer") + return errors.New("cannot inspect a nil *DockerContainer") } if len(d.ContainerId) == 0 { @@ -187,7 +187,7 @@ func (d *DockerContainer) Inspect() error { func (d *DockerContainer) Logs() (io.ReadCloser, error) { if d == nil { - return nil, errors.New("Cannot view logs for a nil *DockerContainer") + return nil, errors.New("cannot view logs for a nil *DockerContainer") } if len(d.ContainerId) == 0 { return nil, errors.New("missing containerId")