Compare commits

...

65 Commits
v1.0.0 ... main

Author SHA1 Message Date
renovate[bot] 70f0d4e5b3 chore(deps): update dependency golangci/golangci-lint to v1.58.1 2024-05-13 04:56:02 +00:00
Robert Kaussow 9ff6cd2e6a
ci: fix golangci-lint deprecations 2024-05-12 11:08:22 +02:00
renovate[bot] d36d95846e chore(deps): update dependency golangci/golangci-lint to v1.58.0 2024-05-06 07:57:19 +00:00
renovate[bot] 5c8b9d9cd5
fix(deps): update module github.com/urfave/cli/v2 to v2.27.2 (#91)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-04-29 10:27:12 +02:00
renovate[bot] 77d3c11da1 chore(deps): update dependency golangci/golangci-lint to v1.57.2 2024-04-01 03:29:42 +00:00
renovate[bot] df1cb658f3 chore(deps): update dependency golangci/golangci-lint to v1.57.1 2024-03-25 03:25:18 +00:00
renovate[bot] 659ddcee44 chore(deps): update dependency golangci/golangci-lint to v1.56.2 2024-02-19 03:52:57 +00:00
Robert Kaussow 7d4e9651f5
[skip ci] revert renovate automerge config 2024-02-15 12:19:23 +01:00
renovate[bot] c6b5c9d03d
chore(deps): update dependency golangci/golangci-lint to v1.56.1 (#87)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
2024-02-12 09:09:30 +01:00
renovate[bot] 656f744c52
chore(deps): update docker.io/library/golang docker tag to v1.22 (#86)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
2024-02-07 22:33:53 +01:00
Robert Kaussow b01ea54ae9
run ci on renovate auto branches 2024-02-07 09:10:05 +01:00
Robert Kaussow 6c04899a49
ci: enable ci run on renovate branches 2024-02-05 08:58:24 +01:00
renovate[bot] edbced6e5b
fix(deps): update module github.com/rs/zerolog to v1.32.0 (#85)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-02-05 08:45:18 +01:00
renovate[bot] 8f8506617a chore(deps): update dependency mvdan/gofumpt to v0.6.0 2024-01-30 08:40:32 +00:00
renovate[bot] 7cbec15ac2
fix(deps): update module github.com/urfave/cli/v2 to v2.27.1 (#83)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-01-01 16:21:59 +01:00
Robert Kaussow 5f80b2a7f3
use list style synatx and cleanup (#82) 2023-12-23 23:43:43 +01:00
Robert Kaussow 8c4de70ec4
ci: add missing test group 2023-12-15 22:34:42 +01:00
Robert Kaussow b5214bd5df
fix: replace logrus by zerolog (#81) 2023-12-06 09:14:10 +01:00
renovate[bot] 697fdd8bbe
fix(deps): update module github.com/urfave/cli/v2 to v2.26.0 (#78)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-12-04 10:15:35 +01:00
Robert Kaussow 872985ac58
fix: rename host flag alias from h to ht (#80)
BREAKING CHANGE: The alias `h` for the `host` flag was in conflict with the default help alias and was renamed to `ht`.
2023-12-04 09:55:56 +01:00
Robert Kaussow 930e1aac89
remove deprecated go version from golangci config 2023-11-08 09:25:24 +01:00
renovate[bot] 590a1c2373 chore(deps): update dependency golangci/golangci-lint to v1.55.2 2023-11-06 03:16:54 +00:00
renovate[bot] 9c841c24cd chore(deps): update dependency golangci/golangci-lint to v1.55.1 2023-10-30 03:47:03 +00:00
Robert Kaussow 49348198db
ci: use gotestsum for better test output (#75) 2023-10-29 16:03:41 +01:00
Robert Kaussow 8fbc353b9b
use uppercase title for breaking changes in changelog 2023-10-28 22:59:46 +02:00
renovate[bot] a6c765e1ae chore(deps): update dependency golangci/golangci-lint to v1.55.0 2023-10-23 03:58:46 +00:00
Robert Kaussow 63a38bd033
docs: fix installation instructions (#73) 2023-10-17 14:38:17 +02:00
Robert Kaussow f246b1d280
ci: fix changelog generation for tag events (#72) 2023-10-17 14:03:25 +02:00
Robert Kaussow 48bead3372
ci: fix releases and add linkcheck (#71) 2023-10-17 00:36:07 +02:00
renovate[bot] ff7cdd0857 chore(deps): update dependency golangci/golangci-lint to v1.54.2 2023-08-28 04:39:29 +00:00
Robert Kaussow 6bf5fa8754
fix gitignore 2023-08-22 22:24:12 +02:00
Robert Kaussow ae1fc2e698
fix ci 2023-08-22 09:55:47 +02:00
Robert Kaussow 8c8961bc8e
unify ci 2023-08-22 09:46:00 +02:00
Robert Kaussow c0724d12f2
fix ci 2023-08-22 09:04:28 +02:00
Robert Kaussow 2a55822632
ci: temp remove codecov 2023-08-21 16:20:48 +02:00
Robert Kaussow 90072d2d43
ci: migrate to woodpecker (#69) 2023-08-21 16:06:34 +02:00
renovate[bot] 19af4c5c47 chore(deps): update dependency golangci/golangci-lint to v1.54.1 2023-08-14 04:28:47 +00:00
Robert Kaussow 8457c57394
fix: fallback to stdin automatically if no url provided by flag (#67)
* fix: fallback to stdin automatically if no url provided by flag

* cleanup
2023-07-23 10:02:46 +02:00
Robert Kaussow 0af993f5b1
feat: add option to read url from stdin (#66) 2023-07-19 20:39:30 +02:00
renovate[bot] db299322bc
fix(deps): update module github.com/urfave/cli/v2 to v2.25.7 (#63)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-07-19 15:56:51 +02:00
Robert Kaussow 3875ad7a2c
refactor: rework project structure to use config struct (#65) 2023-07-19 15:56:43 +02:00
renovate[bot] 3a220af100 chore(deps): update dependency golangci/golangci-lint to v1.53.3 2023-06-19 03:37:49 +00:00
renovate[bot] c35952c307
fix(deps): update module github.com/urfave/cli/v2 to v2.25.5 (#60)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 10:24:23 +02:00
renovate[bot] 183d422439
fix(deps): update module github.com/sirupsen/logrus to v1.9.3 (#59)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-06-05 10:00:40 +02:00
renovate[bot] 96db2914ca
chore(deps): update dependency golangci/golangci-lint to v1.53.2 (#61)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Robert Kaussow <mail@thegeeklab.de>
2023-06-05 09:52:33 +02:00
renovate[bot] 1c77303641
fix(deps): update module github.com/urfave/cli/v2 to v2.25.4 (#55)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-28 15:20:09 +02:00
renovate[bot] 2f99efb570
fix(deps): update module github.com/sirupsen/logrus to v1.9.2 (#58)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2023-05-26 10:59:04 +02:00
Robert Kaussow 65184f6fc9
fix bare url in contribution file (#57) 2023-05-03 11:50:07 +02:00
renovate[bot] ffd126bf10 chore(deps): update dependency mvdan/gofumpt to v0.5.0 2023-04-17 05:35:11 +00:00
renovate[bot] cf8701ad2f chore(deps): update dependency golangci/golangci-lint to v1.52.2 2023-03-27 02:05:34 +00:00
renovate[bot] f8585dd93b chore(deps): update dependency golangci/golangci-lint to v1.52.0 2023-03-20 05:13:38 +00:00
renovate[bot] 364ccf7c84 chore(deps): update dependency golangci/golangci-lint to v1.51.2 2023-02-27 06:52:51 +00:00
Robert Kaussow 13171987d8
fix drone-matrix template 2023-02-08 17:04:29 +01:00
Robert Kaussow ddd51bf1c6
refactor: add more linters and fix findings (#49) 2023-02-08 10:13:55 +01:00
renovate[bot] 870aef309e chore(deps): update dependency golangci/golangci-lint to v1.51.1 2023-02-06 05:22:50 +00:00
renovate[bot] 067b1bf449
fix(deps): update module github.com/urfave/cli/v2 to v2.24.3 (#47) 2023-02-03 08:48:29 +01:00
Robert Kaussow 887fbb90e1
unify makefile syntax (#46) 2023-01-14 22:57:49 +01:00
Robert Kaussow 5c61c96e14
add goarm handling in makefile (#45) 2023-01-14 15:46:27 +01:00
renovate[bot] 98277d747e
fix(deps): update module github.com/urfave/cli/v2 to v2.23.7 (#44) 2022-12-20 21:06:58 +01:00
renovate[bot] 8a8c51409c
fix(deps): update module github.com/urfave/cli/v2 to v2.23.5 (#39) 2022-11-24 09:46:35 +01:00
Robert Kaussow f32e067fbe
ci: create symlink for xgo source directory (#43) 2022-11-24 09:43:47 +01:00
renovate[bot] fd7629faf3 chore(deps): update dependency golangci/golangci-lint to v1.50.1 2022-10-24 05:31:38 +00:00
renovate[bot] 5a6af40cd7 chore(deps): update golang dev tools (non-major) 2022-10-10 03:40:31 +00:00
renovate[bot] 2738dd3870 chore(deps): update dependency golangci/golangci-lint to v1.49.0 2022-08-29 04:45:59 +00:00
renovate[bot] ba386afbb5 chore(deps): update dependency golangci/golangci-lint to v1.48.0 2022-08-08 03:36:02 +00:00
53 changed files with 748 additions and 841 deletions

View File

@ -1,23 +0,0 @@
# Changelog
{{ range .Versions -}}
## {{ if .Tag.Previous }}[{{ .Tag.Name }}]({{ $.Info.RepositoryURL }}/compare/{{ .Tag.Previous.Name }}...{{ .Tag.Name }}){{ else }}{{ .Tag.Name }}{{ end }} ({{ datetime "2006-01-02" .Tag.Date }})
{{ range .CommitGroups -}}
### {{ .Title }}
{{ range .Commits -}}
- {{ if .Scope }}**{{ .Scope }}:** {{ end }}{{ (regexReplaceAll "(.*)/issues/(.*)" (regexReplaceAll "(Co-\\w*-by.*)" .Subject "") "${1}/pull/${2}") | trim }}
{{ end }}
{{- end -}}
{{- if .NoteGroups -}}
{{ range .NoteGroups -}}
### {{ .Title }}
{{ range .Notes }}
{{ .Body }}
{{ end }}
{{ end -}}
{{ end -}}
{{ end -}}

View File

@ -1,25 +0,0 @@
style: github
template: CHANGELOG.tpl.md
info:
title: CHANGELOG
repository_url: https://github.com/thegeeklab/url-parser
options:
commit_groups:
title_maps:
feat: Features
fix: Bug Fixes
perf: Performance Improvements
refactor: Code Refactoring
chore: Others
test: Testing
ci: CI Pipeline
docs: Documentation
header:
pattern: "^(\\w*)(?:\\(([\\w\\$\\.\\-\\*\\s]*)\\))?\\:\\s(.*)$"
pattern_maps:
- Type
- Scope
- Subject
notes:
keywords:
- BREAKING CHANGE

4
.dictionary Normal file
View File

@ -0,0 +1,4 @@
url-parser
herloct
multiarch
(P|p)rebuilt

View File

@ -1,2 +0,0 @@
*
!dist/

View File

@ -1,174 +0,0 @@
local PipelineTest = {
kind: 'pipeline',
name: 'test',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'deps',
image: 'golang:1.19',
commands: [
'make deps',
],
volumes: [
{
name: 'godeps',
path: '/go',
},
],
},
{
name: 'lint',
image: 'golang:1.19',
commands: [
'make lint',
],
volumes: [
{
name: 'godeps',
path: '/go',
},
],
},
{
name: 'test',
image: 'golang:1.19',
commands: [
'make test',
],
volumes: [
{
name: 'godeps',
path: '/go',
},
],
},
{
name: 'coverage',
image: 'plugins/codecov',
settings: {
token: {
from_secret: 'codecov_token',
},
files: [
'coverage.out',
],
},
},
],
volumes: [
{
name: 'godeps',
temp: {},
},
],
trigger: {
ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
},
};
local PipelineBuildBinaries = {
kind: 'pipeline',
name: 'build-binaries',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'build',
image: 'techknowlogick/xgo:go-1.19.x',
commands: [
'make release',
],
},
{
name: 'executable',
image: 'alpine',
commands: [
'$(find dist/ -executable -type f -iname ${DRONE_REPO_NAME}-linux-amd64) --help',
],
},
{
name: 'changelog-generate',
image: 'thegeeklab/git-chglog',
commands: [
'git fetch -tq',
'git-chglog --no-color --no-emoji -o CHANGELOG.md ${DRONE_TAG:---next-tag unreleased unreleased}',
],
},
{
name: 'changelog-format',
image: 'thegeeklab/alpine-tools',
commands: [
'prettier CHANGELOG.md',
'prettier -w CHANGELOG.md',
],
},
{
name: 'publish',
image: 'plugins/github-release',
settings: {
overwrite: true,
api_key: {
from_secret: 'github_token',
},
files: ['dist/*'],
title: '${DRONE_TAG}',
note: 'CHANGELOG.md',
},
when: {
ref: [
'refs/tags/**',
],
},
},
],
depends_on: [
'test',
],
trigger: {
ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
},
};
local PipelineNotifications = {
kind: 'pipeline',
name: 'notifications',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'matrix',
image: 'thegeeklab/drone-matrix',
settings: {
homeserver: { from_secret: 'matrix_homeserver' },
roomid: { from_secret: 'matrix_roomid' },
template: 'Status: **{{ build.Status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.Link }}){{#if build.Branch}} ({{ build.Branch }}){{/if}} by {{ commit.Author }}<br/> Message: {{ commit.Message.Title }}',
username: { from_secret: 'matrix_username' },
password: { from_secret: 'matrix_password' },
},
when: {
status: ['success', 'failure'],
},
},
],
depends_on: [
'build-binaries',
],
trigger: {
ref: ['refs/heads/main', 'refs/tags/**'],
status: ['success', 'failure'],
},
};
[
PipelineTest,
PipelineBuildBinaries,
PipelineNotifications,
]

View File

@ -1,147 +0,0 @@
---
kind: pipeline
name: test
platform:
os: linux
arch: amd64
steps:
- name: deps
image: golang:1.19
commands:
- make deps
volumes:
- name: godeps
path: /go
- name: lint
image: golang:1.19
commands:
- make lint
volumes:
- name: godeps
path: /go
- name: test
image: golang:1.19
commands:
- make test
volumes:
- name: godeps
path: /go
- name: coverage
image: plugins/codecov
settings:
files:
- coverage.out
token:
from_secret: codecov_token
volumes:
- name: godeps
temp: {}
trigger:
ref:
- refs/heads/main
- refs/tags/**
- refs/pull/**
---
kind: pipeline
name: build-binaries
platform:
os: linux
arch: amd64
steps:
- name: build
image: techknowlogick/xgo:go-1.19.x
commands:
- make release
- name: executable
image: alpine
commands:
- $(find dist/ -executable -type f -iname ${DRONE_REPO_NAME}-linux-amd64) --help
- name: changelog-generate
image: thegeeklab/git-chglog
commands:
- git fetch -tq
- git-chglog --no-color --no-emoji -o CHANGELOG.md ${DRONE_TAG:---next-tag unreleased unreleased}
- name: changelog-format
image: thegeeklab/alpine-tools
commands:
- prettier CHANGELOG.md
- prettier -w CHANGELOG.md
- name: publish
image: plugins/github-release
settings:
api_key:
from_secret: github_token
files:
- dist/*
note: CHANGELOG.md
overwrite: true
title: ${DRONE_TAG}
when:
ref:
- refs/tags/**
trigger:
ref:
- refs/heads/main
- refs/tags/**
- refs/pull/**
depends_on:
- test
---
kind: pipeline
name: notifications
platform:
os: linux
arch: amd64
steps:
- name: matrix
image: thegeeklab/drone-matrix
settings:
homeserver:
from_secret: matrix_homeserver
password:
from_secret: matrix_password
roomid:
from_secret: matrix_roomid
template: "Status: **{{ build.Status }}**<br/> Build: [{{ repo.Owner }}/{{ repo.Name }}]({{ build.Link }}){{#if build.Branch}} ({{ build.Branch }}){{/if}} by {{ commit.Author }}<br/> Message: {{ commit.Message.Title }}"
username:
from_secret: matrix_username
when:
status:
- success
- failure
trigger:
ref:
- refs/heads/main
- refs/tags/**
status:
- success
- failure
depends_on:
- build-binaries
---
kind: signature
hmac: 7b57366e668a7949629efd424ba0b8a4483c959dea819dcd0ec7f001763cfcb4
...

View File

@ -50,7 +50,9 @@ branches:
required_status_checks:
strict: false
contexts:
- continuous-integration/drone/pr
enforce_admins: true
- ci/woodpecker/pr/test
- ci/woodpecker/pr/build-package
- ci/woodpecker/pr/docs
enforce_admins: false
required_linear_history: true
restrictions: null

4
.gitignore vendored
View File

@ -1,5 +1,5 @@
/dist/
/release/
/dist
/release
/url-parser*
coverage.out

47
.gitsv/config.yml Normal file
View File

@ -0,0 +1,47 @@
---
version: "1.1"
versioning:
update-major: []
update-minor: [feat]
update-patch: [fix, perf, refactor, chore, test, ci, docs]
tag:
pattern: "v%d.%d.%d"
release-notes:
sections:
- name: Features
commit-types: [feat]
section-type: commits
- name: Bug Fixes
commit-types: [fix]
section-type: commits
- name: Performance Improvements
commit-types: [perf]
section-type: commits
- name: Code Refactoring
commit-types: [refactor]
section-type: commits
- name: Others
commit-types: [chore]
section-type: commits
- name: Testing
commit-types: [test]
section-type: commits
- name: CI Pipeline
commit-types: [ci]
section-type: commits
- name: Documentation
commit-types: [docs]
section-type: commits
- name: BREAKING CHANGES
section-type: breaking-changes
commit-message:
footer:
issue:
key: issue
add-value-prefix: "#"
issue:
regex: "#?[0-9]+"

View File

@ -1,25 +1,91 @@
linters:
enable:
- gosimple
- deadcode
- typecheck
- govet
- errcheck
- staticcheck
- unused
- structcheck
- varcheck
- dupl
- gofmt
- misspell
- gocritic
- bidichk
- ineffassign
- revive
- gofumpt
- depguard
enable-all: false
disable-all: true
enable:
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- typecheck
- unused
- asasalint
- asciicheck
- bidichk
- bodyclose
- containedctx
- contextcheck
- decorder
- dogsled
- dupl
- dupword
- durationcheck
- errchkjson
- errname
- errorlint
- exhaustive
- exportloopref
- forcetypeassert
- ginkgolinter
- gocheckcompilerdirectives
- gochecknoglobals
- gochecknoinits
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- godox
- err113
- gofmt
- gofumpt
- goheader
- goimports
- mnd
- gomoddirectives
- gomodguard
- goprintffuncname
- gosec
- grouper
- importas
- interfacebloat
- ireturn
- lll
- loggercheck
- maintidx
- makezero
- misspell
- musttag
- nakedret
- nestif
- nilerr
- nilnil
- nlreturn
- noctx
- nolintlint
- nonamedreturns
- nosprintfhostport
- prealloc
- predeclared
- promlinter
- reassign
- revive
# - rowserrcheck
# - sqlclosecheck
# - structcheck
- stylecheck
- tagliatelle
- tenv
- testableexamples
- thelper
- tparallel
- unconvert
- unparam
- usestdlibvars
# - wastedassign
- whitespace
- wsl
- zerologlint
fast: false
run:
@ -28,4 +94,3 @@ run:
linters-settings:
gofumpt:
extra-rules: true
lang-version: "1.18"

6
.markdownlint.yml Normal file
View File

@ -0,0 +1,6 @@
---
default: True
MD013: False
MD041: False
MD004:
style: dash

View File

@ -1,3 +1,2 @@
.drone.yml
*.tpl.md
LICENSE

View File

@ -0,0 +1,41 @@
---
when:
- event: [pull_request, tag]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
- name: build
image: docker.io/techknowlogick/xgo:go-1.22.x
commands:
- ln -s $(pwd) /source
- make release
- name: executable
image: quay.io/thegeeklab/alpine-tools
commands:
- $(find dist/ -executable -type f -iname ${CI_REPO_NAME}-linux-amd64) --help
- name: changelog
image: quay.io/thegeeklab/git-sv
commands:
- git sv current-version
- git sv release-notes -t ${CI_COMMIT_TAG:-next} -o CHANGELOG.md
- cat CHANGELOG.md
- name: publish-github
image: docker.io/plugins/github-release
settings:
api_key:
from_secret: github_token
files:
- dist/*
note: CHANGELOG.md
overwrite: true
title: ${CI_COMMIT_TAG}
when:
- event: [tag]
depends_on:
- test

22
.woodpecker/docs.yml Normal file
View File

@ -0,0 +1,22 @@
---
when:
- event: [pull_request, tag]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
- name: markdownlint
image: quay.io/thegeeklab/markdownlint-cli
commands:
- markdownlint 'README.md' 'CONTRIBUTING.md'
- name: spellcheck
image: quay.io/thegeeklab/alpine-tools
commands:
- spellchecker --files 'README.md' 'CONTRIBUTING.md' -d .dictionary -p spell indefinite-article syntax-urls
environment:
FORCE_COLOR: "true"
depends_on:
- build-package

26
.woodpecker/notify.yml Normal file
View File

@ -0,0 +1,26 @@
---
when:
- event: [tag]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
runs_on: [success, failure]
steps:
- name: matrix
image: quay.io/thegeeklab/wp-matrix
settings:
homeserver:
from_secret: matrix_homeserver
password:
from_secret: matrix_password
roomid:
from_secret: matrix_roomid
username:
from_secret: matrix_username
when:
- status: [success, failure]
depends_on:
- docs

17
.woodpecker/test.yml Normal file
View File

@ -0,0 +1,17 @@
---
when:
- event: [pull_request, tag]
- event: [push, manual]
branch:
- ${CI_REPO_DEFAULT_BRANCH}
steps:
- name: lint
image: docker.io/library/golang:1.22
commands:
- make lint
- name: test
image: docker.io/library/golang:1.22
commands:
- make test

View File

@ -3,7 +3,7 @@
## Security
If you think you have found a **security issue**, please do not mention it in this repository.
Instead, send an email to security@thegeeklab.de with as many details as possible so it can be handled confidential.
Instead, send an email to `security@thegeeklab.de` with as many details as possible so it can be handled confidential.
## Bug Reports and Feature Requests

View File

@ -1,7 +1,7 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.3.1
GOFUMPT_PACKAGE_VERSION := v0.6.0
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.47.2
GOLANGCI_LINT_PACKAGE_VERSION := v1.58.1
EXECUTABLE := url-parser
@ -17,16 +17,22 @@ SOURCES ?= $(shell find . -name "*.go" -type f)
GOFUMPT_PACKAGE ?= mvdan.cc/gofumpt@$(GOFUMPT_PACKAGE_VERSION)
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/golangci-lint@$(GOLANGCI_LINT_PACKAGE_VERSION)
XGO_PACKAGE ?= src.techknowlogick.com/xgo@latest
GOTESTSUM_PACKAGE ?= gotest.tools/gotestsum@latest
GENERATE ?=
XGO_VERSION := go-1.19.x
XGO_VERSION := go-1.22.x
XGO_TARGETS ?= linux/amd64,linux/arm-6,linux/arm-7,linux/arm64
TARGETOS ?= linux
TARGETARCH ?= amd64
ifneq ("$(TARGETVARIANT)","")
GOARM ?= $(subst v,,$(TARGETVARIANT))
endif
TAGS ?= netgo
ifndef VERSION
ifneq ($(DRONE_TAG),)
VERSION ?= $(subst v,,$(DRONE_TAG))
ifneq ($(CI_COMMIT_TAG),)
VERSION ?= $(subst v,,$(CI_COMMIT_TAG))
else
VERSION ?= $(shell git rev-parse --short HEAD)
endif
@ -63,13 +69,13 @@ generate:
.PHONY: test
test:
$(GO) test -v -coverprofile coverage.out $(PACKAGES)
$(GO) run $(GOTESTSUM_PACKAGE) --no-color=false -- -coverprofile=coverage.out $(PACKAGES)
.PHONY: build
build: $(DIST)/$(EXECUTABLE)
$(DIST)/$(EXECUTABLE): $(SOURCES)
$(GO) build -v -tags '$(TAGS)' -ldflags '-extldflags "-static" $(LDFLAGS)' -o $@ ./cmd/$(EXECUTABLE)
GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) GOARM=$(GOARM) $(GO) build -v -tags '$(TAGS)' -ldflags '-extldflags "-static" $(LDFLAGS)' -o $@ ./cmd/$(EXECUTABLE)
$(DIST_DIRS):
mkdir -p $(DIST_DIRS)
@ -94,3 +100,4 @@ deps:
$(GO) install $(GOFUMPT_PACKAGE)
$(GO) install $(GOLANGCI_LINT_PACKAGE)
$(GO) install $(XGO_PACKAGE)
$(GO) install $(GOTESTSUM_PACKAGE)

View File

@ -1,8 +1,9 @@
# url-parser
[![Build Status](https://img.shields.io/drone/build/thegeeklab/url-parser?logo=drone&server=https%3A%2F%2Fdrone.thegeeklab.de)](https://drone.thegeeklab.de/thegeeklab/url-parser)
Simple command-line URL parser
[![Build Status](https://ci.thegeeklab.de/api/badges/thegeeklab/url-parser/status.svg)](https://ci.thegeeklab.de/repos/thegeeklab/url-parser)
[![Go Report Card](https://goreportcard.com/badge/github.com/thegeeklab/url-parser)](https://goreportcard.com/report/github.com/thegeeklab/url-parser)
[![Codecov](https://img.shields.io/codecov/c/github/thegeeklab/url-parser)](https://codecov.io/gh/thegeeklab/url-parser)
[![GitHub contributors](https://img.shields.io/github/contributors/thegeeklab/url-parser)](https://github.com/thegeeklab/url-parser/graphs/contributors)
[![License: MIT](https://img.shields.io/github/license/thegeeklab/url-parser)](https://github.com/thegeeklab/url-parser/blob/main/LICENSE)
@ -10,12 +11,11 @@ Inspired by [herloct/url-parser](https://github.com/herloct/url-parser), a simpl
## Installation
Prebuild multiarch binaries are availabe for Linux only:
Prebuilt multiarch binaries are available for Linux only.
```Shell
curl -L https://github.com/thegeeklab/url-parser/releases/download/v0.1.0/url-parser-0.1.0-linux-amd64 > /usr/local/bin/url-parser
curl -SsfL https://github.com/thegeeklab/url-parser/releases/latest/download/url-parser-linux-amd64 -o /usr/local/bin/url-parser
chmod +x /usr/local/bin/url-parser
url-parser --help
```
## Build
@ -23,11 +23,6 @@ url-parser --help
Build the binary from source with the following command:
```Shell
export GOOS=linux
export GOARCH=amd64
export CGO_ENABLED=0
export GO111MODULE=on
make build
```
@ -58,30 +53,34 @@ COMMANDS:
GLOBAL OPTIONS:
--url value source url to parse [$URL_PARSER_URL]
--help, -h show help (default: false)
--version, -v print the version (default: false)
--help, -h show help
--version, -v print the version
```
## Examples
```Shell
$ url-parser host --url https://somedomain.com
$ url-parser --url https://somedomain.com host
somedomain.com
$ url-parser user --url https://herloct@somedomain.com
$ url-parser --url https://herloct@somedomain.com user
herloct
$ url-parser path --url https://somedomain.com/path/to
$ url-parser --url https://somedomain.com/path/to path
/path/to
$ url-parser path --path-index=1 --url https://somedomain.com/path/to
$ url-parser --url https://somedomain.com/path/to path --path-index=1
to
$ url-parser query --url https://somedomain.com/?some-key=somevalue
$ url-parser --url https://somedomain.com/?some-key=somevalue query
some-key=somevalue
$ url-parser query --query-field=some-key --url https://somedomain.com/?some-key=somevalue
$ url-parser --url https://somedomain.com/?some-key=somevalue query --query-field=some-key
somevalue
# It is also possible to read the URL from stdin
$ echo "https://somedomain.com" | url-parser host
somedomain.com
```
## Contributors

View File

@ -1,84 +0,0 @@
package main
import (
"github.com/thegeeklab/url-parser/internal/command"
"github.com/urfave/cli/v2"
)
func globalFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "url",
Usage: "source url to parse",
EnvVars: []string{"URL_PARSER_URL"},
},
}
}
func configCommands() []*cli.Command {
return []*cli.Command{
{
Name: "all",
Aliases: []string{"a"},
Usage: "Get all parts from url",
Action: command.Run,
Flags: globalFlags(),
},
{
Name: "scheme",
Aliases: []string{"s"},
Usage: "Get scheme from url",
Action: command.Scheme,
Flags: globalFlags(),
},
{
Name: "user",
Aliases: []string{"u"},
Usage: "Get username from url",
Action: command.User,
Flags: globalFlags(),
},
{
Name: "password",
Aliases: []string{"pw"},
Usage: "Get password from url",
Action: command.Password,
Flags: globalFlags(),
},
{
Name: "path",
Aliases: []string{"pt"},
Usage: "Get path from url",
Action: command.Path,
Flags: append(globalFlags(), command.PathFlags()...),
},
{
Name: "host",
Aliases: []string{"h"},
Usage: "Get hostname from url",
Action: command.Host,
Flags: globalFlags(),
},
{
Name: "port",
Aliases: []string{"p"},
Usage: "Get port from url",
Action: command.Port,
Flags: globalFlags(),
},
{
Name: "query",
Aliases: []string{"q"},
Usage: "Get query from url",
Action: command.Query,
Flags: append(globalFlags(), command.QueryFlags()...),
},
{
Name: "fragment",
Aliases: []string{"f"},
Usage: "Get fragment from url",
Action: command.Fragment,
Flags: globalFlags(),
},
}
}

View File

@ -2,32 +2,124 @@ package main
import (
"fmt"
"io"
"os"
"strings"
"github.com/sirupsen/logrus"
"github.com/thegeeklab/url-parser/internal/command"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/thegeeklab/url-parser/command"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
//nolint:gochecknoglobals
var (
BuildVersion = "devel"
BuildDate = "00000000"
)
func main() {
log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
cli.VersionPrinter = func(c *cli.Context) {
fmt.Printf("%s version=%s date=%s\n", c.App.Name, c.App.Version, BuildDate)
}
app := cli.NewApp()
app.Name = "url-parser"
app.Usage = "Parse URL and shows the part of it."
app.Version = BuildVersion
app.Action = command.Run
app.Flags = globalFlags()
app.Commands = configCommands()
cfg := &config.Config{}
app := &cli.App{
Name: "url-parser",
Usage: "Parse URL and shows the part of it.",
Version: BuildVersion,
Action: command.Run(cfg),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "url",
Usage: "source url to parse",
EnvVars: []string{"URL_PARSER_URL"},
Destination: &cfg.URL,
},
},
Commands: []*cli.Command{
{
Name: "all",
Aliases: []string{"a"},
Usage: "Get all parts from url",
Action: command.Run(cfg),
},
{
Name: "scheme",
Aliases: []string{"s"},
Usage: "Get scheme from url",
Action: command.Scheme(cfg),
},
{
Name: "user",
Aliases: []string{"u"},
Usage: "Get username from url",
Action: command.User(cfg),
},
{
Name: "password",
Aliases: []string{"pw"},
Usage: "Get password from url",
Action: command.Password(cfg),
},
{
Name: "path",
Aliases: []string{"pt"},
Usage: "Get path from url",
Action: command.Path(cfg),
Flags: command.PathFlags(cfg),
},
{
Name: "host",
Aliases: []string{"ht"},
Usage: "Get hostname from url",
Action: command.Host(cfg),
},
{
Name: "port",
Aliases: []string{"p"},
Usage: "Get port from url",
Action: command.Port(cfg),
},
{
Name: "query",
Aliases: []string{"q"},
Usage: "Get query from url",
Action: command.Query(cfg),
Flags: command.QueryFlags(cfg),
},
{
Name: "fragment",
Aliases: []string{"f"},
Usage: "Get fragment from url",
Action: command.Fragment(cfg),
},
},
Before: func(_ *cli.Context) error {
if cfg.URL == "" {
stat, _ := os.Stdin.Stat()
if (stat.Mode() & os.ModeCharDevice) == 0 {
stdin, err := io.ReadAll(os.Stdin)
if err != nil {
return fmt.Errorf("error: %w: %w", config.ErrReadStdin, err)
}
cfg.URL = strings.TrimSuffix(string(stdin), "\n")
}
}
if cfg.URL == "" {
return fmt.Errorf("error: %w", config.ErrEmptyURL)
}
return nil
},
}
if err := app.Run(os.Args); err != nil {
logrus.Fatal(err)
log.Fatal().Err(err).Msg("Execution error")
}
}

View File

@ -4,7 +4,8 @@ import (
"net/url"
"strings"
"github.com/sirupsen/logrus"
"github.com/rs/zerolog/log"
"github.com/thegeeklab/url-parser/config"
)
func parseURL(raw string) *url.URL {
@ -12,7 +13,7 @@ func parseURL(raw string) *url.URL {
url, err := url.Parse(urlString)
if err != nil {
logrus.Fatal(err)
log.Fatal().Err(err).Msg(config.ErrParseURL.Error())
}
return url

View File

@ -1,19 +1,24 @@
package command
import "testing"
import (
"testing"
"github.com/thegeeklab/url-parser/config"
)
type TestParseData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestParseURL(t *testing.T) {
//nolint:goconst
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestParseData{
{
urlString: urlString,
expected: urlString,
config: &config.Config{URL: urlString},
expected: urlString,
},
}

21
command/fragment.go Normal file
View File

@ -0,0 +1,21 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// Fragment prints out the fragment part from the url.
func Fragment(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
if len(parts.Scheme) > 0 {
fmt.Println(parts.Fragment)
}
return nil
}
}

View File

@ -1,17 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestFragmentData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestFragment(t *testing.T) {
@ -19,18 +19,16 @@ func TestFragment(t *testing.T) {
tables := []TestFragmentData{
{
urlString: urlString,
expected: "some-fragment",
config: &config.Config{URL: urlString},
expected: "some-fragment",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Fragment(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Fragment(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL fragment `%v`, should be `%v`", result, table.expected)

21
command/host.go Normal file
View File

@ -0,0 +1,21 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// Host prints out the host part from the url.
func Host(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
if len(parts.Scheme) > 0 {
fmt.Println(parts.Hostname())
}
return nil
}
}

View File

@ -1,17 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestHostnameData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestHost(t *testing.T) {
@ -19,18 +19,16 @@ func TestHost(t *testing.T) {
tables := []TestHostnameData{
{
urlString: urlString,
expected: "host.com",
config: &config.Config{URL: urlString},
expected: "host.com",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Host(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Host(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL host `%v`, should be `%v`", result, table.expected)

24
command/password.go Normal file
View File

@ -0,0 +1,24 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// Password prints out the password part from url.
func Password(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
if parts.User != nil {
pw, _ := parts.User.Password()
if len(pw) > 0 {
fmt.Println(pw)
}
}
return nil
}
}

View File

@ -1,17 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestPasswordData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestPassword(t *testing.T) {
@ -19,18 +19,16 @@ func TestPassword(t *testing.T) {
tables := []TestPasswordData{
{
urlString: urlString,
expected: "pass",
config: &config.Config{URL: urlString},
expected: "pass",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Password(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Password(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL password `%v`, should be `%v`", result, table.expected)

44
command/path.go Normal file
View File

@ -0,0 +1,44 @@
package command
import (
"fmt"
"strings"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// PathFlags defines flags for path subcommand.
func PathFlags(cfg *config.Config) []cli.Flag {
return []cli.Flag{
&cli.IntFlag{
Name: "path-index",
Usage: "filter parsed path by index",
EnvVars: []string{"URL_PARSER_PATH_INDEX"},
Value: -1,
Destination: &cfg.PathIndex,
},
}
}
// Path prints out the path part from url.
func Path(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
i := cfg.PathIndex
if len(parts.Path) > 0 {
if i > -1 {
path := strings.Split(parts.Path, "/")
if i++; i < len(path) {
fmt.Println(path[i])
}
} else {
fmt.Println(parts.Path)
}
}
return nil
}
}

View File

@ -1,18 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestPathData struct {
urlString string
pathIndex int
expected string
config *config.Config
expected string
}
func TestPath(t *testing.T) {
@ -20,25 +19,20 @@ func TestPath(t *testing.T) {
tables := []TestPathData{
{
urlString: urlString,
pathIndex: -1,
expected: "/path/to",
config: &config.Config{URL: urlString, PathIndex: -1},
expected: "/path/to",
},
{
urlString: urlString,
pathIndex: 0,
expected: "path",
config: &config.Config{URL: urlString, PathIndex: 0},
expected: "path",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
set.Int("path-index", table.pathIndex, "index")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Path(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Path(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL path `%v`, should be `%v`", result, table.expected)

21
command/port.go Normal file
View File

@ -0,0 +1,21 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// Port prints out the port from the url.
func Port(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
if len(parts.Scheme) > 0 {
fmt.Println(parts.Port())
}
return nil
}
}

View File

@ -1,17 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestPortData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestPort(t *testing.T) {
@ -19,18 +19,16 @@ func TestPort(t *testing.T) {
tables := []TestPortData{
{
urlString: urlString,
expected: "5432",
config: &config.Config{URL: urlString},
expected: "5432",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Port(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Port(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL port `%v`, should be `%v`", result, table.expected)

40
command/query.go Normal file
View File

@ -0,0 +1,40 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// QueryFlags defines flags for query subcommand.
func QueryFlags(cfg *config.Config) []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "query-field",
Usage: "filter parsed query string by field name",
EnvVars: []string{"URL_PARSER_QUERY_FIELD"},
Destination: &cfg.QueryField,
},
}
}
// Query prints out the query part from url.
func Query(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
f := cfg.QueryField
if len(parts.RawQuery) > 0 {
if f != "" {
if result := parts.Query().Get(f); result != "" {
fmt.Println(result)
}
} else {
fmt.Println(parts.RawQuery)
}
}
return nil
}
}

View File

@ -1,16 +1,16 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestQueryData struct {
urlString string
config *config.Config
QueryField string
expected string
}
@ -20,24 +20,21 @@ func TestQuery(t *testing.T) {
tables := []TestQueryData{
{
urlString: urlString,
expected: "key=value&other=other%20value",
config: &config.Config{URL: urlString},
expected: "key=value&other=other%20value",
},
{
urlString: urlString,
QueryField: "other",
expected: "other value",
config: &config.Config{URL: urlString, QueryField: "other"},
expected: "other value",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
set.String("query-field", table.QueryField, "index")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Query(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Query(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL query `%v`, should be `%v`", result, table.expected)

21
command/run.go Normal file
View File

@ -0,0 +1,21 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// Run default command and print out full url.
func Run(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
if len(parts.String()) > 0 {
fmt.Println(parts)
}
return nil
}
}

View File

@ -1,17 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestRunData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestRun(t *testing.T) {
@ -19,18 +19,16 @@ func TestRun(t *testing.T) {
tables := []TestRunData{
{
urlString: urlString,
expected: urlString,
config: &config.Config{URL: urlString},
expected: urlString,
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Run(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Run(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL `%v`, should be `%v`", result, table.expected)

21
command/scheme.go Normal file
View File

@ -0,0 +1,21 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// Scheme prints out the scheme part from the url.
func Scheme(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
if len(parts.Scheme) > 0 {
fmt.Println(parts.Scheme)
}
return nil
}
}

View File

@ -1,17 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestSchemeData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestScheme(t *testing.T) {
@ -19,18 +19,16 @@ func TestScheme(t *testing.T) {
tables := []TestSchemeData{
{
urlString: urlString,
expected: "postgres",
config: &config.Config{URL: urlString},
expected: "postgres",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Scheme(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Scheme(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL scheme `%v`, should be `%v`", result, table.expected)

23
command/user.go Normal file
View File

@ -0,0 +1,23 @@
package command
import (
"fmt"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
)
// User prints out the user part from url.
func User(cfg *config.Config) cli.ActionFunc {
return func(_ *cli.Context) error {
parts := parseURL(cfg.URL)
if parts.User != nil {
if len(parts.User.Username()) > 0 {
fmt.Println(parts.User.Username())
}
}
return nil
}
}

View File

@ -1,17 +1,17 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestUserData struct {
urlString string
expected string
config *config.Config
expected string
}
func TestUser(t *testing.T) {
@ -19,18 +19,16 @@ func TestUser(t *testing.T) {
tables := []TestUserData{
{
urlString: urlString,
expected: "user",
config: &config.Config{URL: urlString},
expected: "user",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
ctx := cli.NewContext(app, nil, nil)
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = User(c) }))
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = User(table.config)(ctx) }))
if result != table.expected {
t.Fatalf("URL user `%v`, should be `%v`", result, table.expected)

15
config/config.go Normal file
View File

@ -0,0 +1,15 @@
package config
import "errors"
var (
ErrEmptyURL = errors.New("no url provided either by \"url\" or \"stdin\"")
ErrReadStdin = errors.New("failed to read \"stdin\"")
ErrParseURL = errors.New("failed to parse url")
)
type Config struct {
URL string
QueryField string
PathIndex int
}

14
go.mod
View File

@ -1,16 +1,18 @@
module github.com/thegeeklab/url-parser
go 1.19
go 1.22
require (
github.com/sirupsen/logrus v1.9.0
github.com/urfave/cli/v2 v2.11.1
github.com/rs/zerolog v1.32.0
github.com/urfave/cli/v2 v2.27.2
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04
)
require (
github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
golang.org/x/sys v0.12.0 // indirect
)

42
go.sum
View File

@ -1,25 +1,25 @@
github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.32.0 h1:keLypqrlIjaFsbmJOBdB/qvyF8KEtCWHwobLp5l/mQ0=
github.com/rs/zerolog v1.32.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/urfave/cli/v2 v2.11.1 h1:UKK6SP7fV3eKOefbS87iT9YHefv7iB/53ih6e+GNAsE=
github.com/urfave/cli/v2 v2.11.1/go.mod h1:f8iq5LtQ/bLxafbdBSLPPNsgaW0l/2fYYEHhAyPlwvo=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04 h1:qXafrlZL1WsJW5OokjraLLRURHiw0OzKHD/RNdspp4w=
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04/go.mod h1:FiwNQxz6hGoNFBC4nIx+CxZhI3nne5RmIOlT/MXcSD4=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 h1:0A+M6Uqn+Eje4kHMK80dtF3JCXC4ykBgQG4Fe06QRhQ=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=

View File

@ -1,17 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// Fragment prints out the fragment part from the url
func Fragment(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
if len(parts.Scheme) > 0 {
fmt.Println(parts.Fragment)
}
return nil
}

View File

@ -1,17 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// Host prints out the host part from the url
func Host(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
if len(parts.Scheme) > 0 {
fmt.Println(parts.Hostname())
}
return nil
}

View File

@ -1,21 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// Password prints out the password part from url
func Password(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
if parts.User != nil {
pw, _ := parts.User.Password()
if len(pw) > 0 {
fmt.Println(pw)
}
}
return nil
}

View File

@ -1,40 +0,0 @@
package command
import (
"fmt"
"strings"
"github.com/urfave/cli/v2"
)
// PathFlags defines flags for path subcommand
func PathFlags() []cli.Flag {
return []cli.Flag{
&cli.IntFlag{
Name: "path-index",
Usage: "filter parsed path by index",
EnvVars: []string{"URL_PARSER_PATH_INDEX"},
Value: -1,
},
}
}
// Path prints out the path part from url
func Path(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
i := ctx.Int("path-index")
if len(parts.Path) > 0 {
if i > -1 {
path := strings.Split(parts.Path, "/")
if i++; i < len(path) {
fmt.Println(path[i])
}
} else {
fmt.Println(parts.Path)
}
}
return nil
}

View File

@ -1,17 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// Port prints out the port from the url
func Port(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
if len(parts.Scheme) > 0 {
fmt.Println(parts.Port())
}
return nil
}

View File

@ -1,36 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// QueryFlags defines flags for query subcommand
func QueryFlags() []cli.Flag {
return []cli.Flag{
&cli.StringFlag{
Name: "query-field",
Usage: "filter parsed query string by field name",
EnvVars: []string{"URL_PARSER_QUERY_FIELD"},
},
}
}
// Query prints out the query part from url
func Query(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
f := ctx.String("query-field")
if len(parts.RawQuery) > 0 {
if f != "" {
if result := parts.Query().Get(f); result != "" {
fmt.Println(result)
}
} else {
fmt.Println(parts.RawQuery)
}
}
return nil
}

View File

@ -1,17 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// Run default command and print out full url
func Run(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
if len(parts.String()) > 0 {
fmt.Println(parts)
}
return nil
}

View File

@ -1,17 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// Scheme prints out the scheme part from the url
func Scheme(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
if len(parts.Scheme) > 0 {
fmt.Println(parts.Scheme)
}
return nil
}

View File

@ -1,19 +0,0 @@
package command
import (
"fmt"
"github.com/urfave/cli/v2"
)
// User prints out the user part from url
func User(ctx *cli.Context) error {
parts := parseURL(ctx.String("url"))
if parts.User != nil {
if len(parts.User.Username()) > 0 {
fmt.Println(parts.User.Username())
}
}
return nil
}