Compare commits

..

101 Commits
v0.2.7 ... main

Author SHA1 Message Date
renovate[bot]
69f5a478ef
chore(deps): update dependency golangci/golangci-lint to v1.62.0 (#112)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-11 03:45:37 +00:00
c00eea41f9
chore: replace deprecated exportloopref golangci linter with copyloopvar 2024-11-08 23:38:30 +01:00
renovate[bot]
18a483485a
chore(deps): update golang patch version (#111)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-08 01:37:07 +00:00
6eb49d0691
consistently pin to golang patch version 2024-11-07 10:36:47 +01:00
d79274f428
feat: add option for json output (#109) 2024-11-05 14:35:26 +01:00
renovate[bot]
6507c1dfa4
fix(deps): update module github.com/urfave/cli/v2 to v2.27.5 (#107)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 10:25:00 +02:00
renovate[bot]
322d1b75b2
chore(deps): update golang minor version (#106)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-03 14:27:04 +02:00
5d65ae5348
add renovate annotation to xgo in makefile 2024-10-02 15:44:10 +02:00
renovate[bot]
75a3f7dc4a chore(deps): update dependency golangci/golangci-lint to v1.61.0 2024-09-16 03:01:36 +00:00
renovate[bot]
7732914f1a
chore(deps): update docker.io/library/golang docker tag to v1.23 (#100)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-02 07:50:23 +02:00
renovate[bot]
776e809c52 chore(deps): update dependency golangci/golangci-lint to v1.60.3 2024-08-26 05:00:34 +00:00
renovate[bot]
4a02590ff2 chore(deps): update golang devdeps non-major 2024-08-19 04:32:00 +00:00
renovate[bot]
8b66ceb9c4
fix(deps): update module github.com/urfave/cli/v2 to v2.27.4 (#99)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-12 08:32:12 +02:00
9238878382
ci: fix notification step 2024-08-07 21:16:45 +02:00
renovate[bot]
ae0cbaa654
fix(deps): update module github.com/urfave/cli/v2 to v2.27.3 (#98)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-08-05 09:09:12 +02:00
renovate[bot]
9047fa86a4 chore(deps): update dependency golangci/golangci-lint to v1.59.1 2024-06-10 04:25:49 +00:00
renovate[bot]
441a10a33d chore(deps): update dependency golangci/golangci-lint to v1.59.0 2024-05-27 03:29:11 +00:00
renovate[bot]
3c053eef7d
fix(deps): update module github.com/rs/zerolog to v1.33.0 (#95)
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-05-24 09:25:36 +02:00
renovate[bot]
cf3d105310 chore(deps): update dependency golangci/golangci-lint to v1.58.2 2024-05-20 07:10:04 +00:00
renovate[bot]
70f0d4e5b3 chore(deps): update dependency golangci/golangci-lint to v1.58.1 2024-05-13 04:56:02 +00:00
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
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
b01ea54ae9
run ci on renovate auto branches 2024-02-07 09:10:05 +01:00
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
5f80b2a7f3
use list style synatx and cleanup (#82) 2023-12-23 23:43:43 +01:00
8c4de70ec4
ci: add missing test group 2023-12-15 22:34:42 +01:00
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
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
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
49348198db
ci: use gotestsum for better test output (#75) 2023-10-29 16:03:41 +01:00
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
63a38bd033
docs: fix installation instructions (#73) 2023-10-17 14:38:17 +02:00
f246b1d280
ci: fix changelog generation for tag events (#72) 2023-10-17 14:03:25 +02:00
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
6bf5fa8754
fix gitignore 2023-08-22 22:24:12 +02:00
ae1fc2e698
fix ci 2023-08-22 09:55:47 +02:00
8c8961bc8e
unify ci 2023-08-22 09:46:00 +02:00
c0724d12f2
fix ci 2023-08-22 09:04:28 +02:00
2a55822632
ci: temp remove codecov 2023-08-21 16:20:48 +02:00
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
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
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
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
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
13171987d8
fix drone-matrix template 2023-02-08 17:04:29 +01:00
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
887fbb90e1
unify makefile syntax (#46) 2023-01-14 22:57:49 +01:00
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
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
renovate[bot]
8ec0eb29be
fix(deps): update module github.com/urfave/cli/v2 to v2.11.1 (#34) 2022-08-05 13:19:46 +02:00
ea23877b4a
chore: switch to go1.19 (#37) 2022-08-05 13:18:27 +02:00
renovate[bot]
255fd776c6 chore(deps): update dependency golangci/golangci-lint to v1.47.2 2022-07-25 03:18:28 +00:00
renovate[bot]
181777004f
fix(deps): update module github.com/sirupsen/logrus to v1.9.0 (#33) 2022-07-21 09:57:02 +02:00
b1f139a722
fix worind in readme and adjust repo config 2022-07-21 09:47:56 +02:00
8d68b98c88
docs: fix spelling in readme 2022-07-12 09:12:32 +02:00
renovate[bot]
37baf6f8ae
fix(deps): update module github.com/urfave/cli/v2 to v2.11.0 (#32) 2022-07-11 08:51:30 +02:00
renovate[bot]
9e1a6398b9
fix(deps): update module github.com/urfave/cli/v2 to v2.10.1 (#31) 2022-06-20 10:27:07 +02:00
renovate[bot]
c2ace14781
fix(deps): update module github.com/urfave/cli/v2 to v2.8.1 (#30) 2022-06-03 10:57:15 +02:00
Renovate Bot
24124e44ae chore(deps): update dependency golangci/golangci-lint to v1.46.2 2022-05-23 06:01:18 +00:00
renovate[bot]
d29e6e23b9
fix(deps): update module github.com/urfave/cli/v2 to v2.7.1 (#28) 2022-05-20 15:52:32 +02:00
7326a7c73d
adjust readme (#27) 2022-05-03 22:48:11 +02:00
renovate[bot]
4668b2512a
fix(deps): update module github.com/urfave/cli/v2 to v2.5.1 (#26) 2022-05-02 21:56:06 +02:00
renovate[bot]
02e19acd42
fix(deps): update module github.com/urfave/cli/v2 to v2.4.8 (#22) 2022-04-25 13:02:29 +02:00
2404e7aeab
ci: refactor build tools and ci setup (#24) 2022-04-25 12:56:32 +02:00
2bd123697f
chore: switch to go1.18 as build requirement (#21) 2022-03-30 22:41:13 +02:00
renovate[bot]
fc011b7533
fix(deps): update module github.com/urfave/cli/v2 to v2.4.0 (#19) 2022-03-27 12:34:29 +02:00
65 changed files with 1377 additions and 1262 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,210 +0,0 @@
local PipelineTest = {
kind: 'pipeline',
image_pull_secrets: ['docker_config'],
name: 'test',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'staticcheck',
image: 'golang:1.16',
commands: [
'go run honnef.co/go/tools/cmd/staticcheck ./...',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'lint',
image: 'golang:1.16',
commands: [
'go run golang.org/x/lint/golint -set_exit_status ./...',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'vet',
image: 'golang:1.16',
commands: [
'go vet ./...',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'test',
image: 'golang:1.16',
commands: [
'go test -race -coverprofile=coverage.txt -covermode=atomic ./...',
],
volumes: [
{
name: 'gopath',
path: '/go',
},
],
},
{
name: 'coverage',
image: 'plugins/codecov',
settings: {
token: {
from_secret: 'codecov_token',
},
files: [
'coverage.txt',
],
},
},
],
volumes: [
{
name: 'gopath',
temp: {},
},
],
trigger: {
ref: ['refs/heads/main', 'refs/tags/**', 'refs/pull/**'],
},
};
local PipelineBuildBinaries = {
kind: 'pipeline',
image_pull_secrets: ['docker_config'],
name: 'build-binaries',
platform: {
os: 'linux',
arch: 'amd64',
},
steps: [
{
name: 'build',
image: 'techknowlogick/xgo:go-1.16.x',
commands: [
'[ -z "${DRONE_TAG}" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}',
'mkdir -p release/',
"cd cmd/url-parser && xgo -ldflags \"-s -w -X main.version=$BUILD_VERSION\" -tags netgo -targets 'linux/amd64,linux/arm-6,linux/arm-7,linux/arm64' -out url-parser .",
'mv /build/* /drone/src/release/',
'ls -l /drone/src/release/',
],
},
{
name: 'executable',
image: 'alpine',
commands: [
'$(find release/ -executable -type f | grep url-parser-linux-amd64) --help',
],
},
{
name: 'compress',
image: 'alpine',
commands: [
'apk add upx',
'find release/ -maxdepth 1 -executable -type f -exec upx {} \\;',
'ls -lh release/',
],
},
{
name: 'checksum',
image: 'alpine',
commands: [
'cd release/ && sha256sum * > sha256sum.txt',
],
},
{
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: ['release/*'],
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',
image_pull_secrets: ['docker_config'],
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,180 +0,0 @@
---
kind: pipeline
name: test
platform:
os: linux
arch: amd64
steps:
- name: staticcheck
image: golang:1.16
commands:
- go run honnef.co/go/tools/cmd/staticcheck ./...
volumes:
- name: gopath
path: /go
- name: lint
image: golang:1.16
commands:
- go run golang.org/x/lint/golint -set_exit_status ./...
volumes:
- name: gopath
path: /go
- name: vet
image: golang:1.16
commands:
- go vet ./...
volumes:
- name: gopath
path: /go
- name: test
image: golang:1.16
commands:
- go test -race -coverprofile=coverage.txt -covermode=atomic ./...
volumes:
- name: gopath
path: /go
- name: coverage
image: plugins/codecov
settings:
files:
- coverage.txt
token:
from_secret: codecov_token
volumes:
- name: gopath
temp: {}
image_pull_secrets:
- docker_config
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.16.x
commands:
- "[ -z \"${DRONE_TAG}\" ] && BUILD_VERSION=${DRONE_COMMIT_SHA:0:8} || BUILD_VERSION=${DRONE_TAG##v}"
- mkdir -p release/
- cd cmd/url-parser && xgo -ldflags "-s -w -X main.version=$BUILD_VERSION" -tags netgo -targets 'linux/amd64,linux/arm-6,linux/arm-7,linux/arm64' -out url-parser .
- mv /build/* /drone/src/release/
- ls -l /drone/src/release/
- name: executable
image: alpine
commands:
- $(find release/ -executable -type f | grep url-parser-linux-amd64) --help
- name: compress
image: alpine
commands:
- apk add upx
- find release/ -maxdepth 1 -executable -type f -exec upx {} \;
- ls -lh release/
- name: checksum
image: alpine
commands:
- cd release/ && sha256sum * > sha256sum.txt
- 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:
- release/*
note: CHANGELOG.md
overwrite: true
title: ${DRONE_TAG}
when:
ref:
- refs/tags/**
image_pull_secrets:
- docker_config
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
image_pull_secrets:
- docker_config
trigger:
ref:
- refs/heads/main
- refs/tags/**
status:
- success
- failure
depends_on:
- build-binaries
---
kind: signature
hmac: 93e1fe6fe0e097355d77fd21bc67f05998e1fccec3848624cc6508f9de8facd9
...

View File

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

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
/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]+"

96
.golangci.yml Normal file
View File

@ -0,0 +1,96 @@
linters:
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
- copyloopvar
- 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:
timeout: 3m
linters-settings:
gofumpt:
extra-rules: true

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.23.3
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
room_id:
from_secret: matrix_room_id
user_id:
from_secret: matrix_user_id
access_token:
from_secret: matrix_access_token
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.23.3
commands:
- make lint
- name: test
image: docker.io/library/golang:1.23.3
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

104
Makefile Normal file
View File

@ -0,0 +1,104 @@
# renovate: datasource=github-releases depName=mvdan/gofumpt
GOFUMPT_PACKAGE_VERSION := v0.7.0
# renovate: datasource=github-releases depName=golangci/golangci-lint
GOLANGCI_LINT_PACKAGE_VERSION := v1.62.0
# renovate: datasource=docker depName=docker.io/techknowlogick/xgo
XGO_PACKAGE_VERSION := go-1.23.3
EXECUTABLE := url-parser
DIST := dist
DIST_DIRS := $(DIST)
IMPORT := github.com/thegeeklab/$(EXECUTABLE)
GO ?= go
CWD ?= $(shell pwd)
PACKAGES ?= $(shell go list ./...)
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_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 ($(CI_COMMIT_TAG),)
VERSION ?= $(subst v,,$(CI_COMMIT_TAG))
else
VERSION ?= $(shell git rev-parse --short HEAD)
endif
endif
ifndef DATE
DATE := $(shell date -u +"%Y-%m-%dT%H:%M:%S%z")
endif
LDFLAGS += -s -w -X "main.BuildVersion=$(VERSION)" -X "main.BuildDate=$(DATE)"
.PHONY: all
all: clean build
.PHONY: clean
clean:
$(GO) clean -i ./...
rm -rf $(DIST_DIRS)
.PHONY: fmt
fmt:
$(GO) run $(GOFUMPT_PACKAGE) -extra -w $(SOURCES)
.PHONY: golangci-lint
golangci-lint:
$(GO) run $(GOLANGCI_LINT_PACKAGE) run
.PHONY: lint
lint: golangci-lint
.PHONY: generate
generate:
$(GO) generate $(GENERATE)
.PHONY: test
test:
$(GO) run $(GOTESTSUM_PACKAGE) --no-color=false -- -coverprofile=coverage.out $(PACKAGES)
.PHONY: build
build: $(DIST)/$(EXECUTABLE)
$(DIST)/$(EXECUTABLE): $(SOURCES)
GOOS=$(TARGETOS) GOARCH=$(TARGETARCH) GOARM=$(GOARM) $(GO) build -v -tags '$(TAGS)' -ldflags '-extldflags "-static" $(LDFLAGS)' -o $@ ./cmd/$(EXECUTABLE)
$(DIST_DIRS):
mkdir -p $(DIST_DIRS)
.PHONY: xgo
xgo: | $(DIST_DIRS)
$(GO) run $(XGO_PACKAGE) -go $(XGO_PACKAGE_VERSION) -v -ldflags '-extldflags "-static" $(LDFLAGS)' -tags '$(TAGS)' -targets '$(XGO_TARGETS)' -out $(EXECUTABLE) --pkg cmd/$(EXECUTABLE) .
cp /build/* $(CWD)/$(DIST)
ls -l $(CWD)/$(DIST)
.PHONY: checksum
checksum:
cd $(DIST); $(foreach file,$(wildcard $(DIST)/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;)
ls -l $(CWD)/$(DIST)
.PHONY: release
release: xgo checksum
.PHONY: deps
deps:
$(GO) mod download
$(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,12 +23,7 @@ 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
go build -v -a -tags netgo -o release/url-parser ./cmd/url-parser/
make build
```
## Usage
@ -39,7 +34,7 @@ NAME:
url-parser - Parse URL and shows the part of it.
USAGE:
url-parser [global options] command [command options] [arguments...]
url-parser [global options] command [command options]
VERSION:
devel
@ -50,7 +45,7 @@ COMMANDS:
user, u Get username from url
password, pw Get password from url
path, pt Get path from url
host, h Get hostname from url
host, ht Get hostname from url
port, p Get port from url
query, q Get query from url
fragment, f Get fragment from url
@ -58,36 +53,43 @@ 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
# Get json output or all parsed parts
$ url-parser --url https://somedomain.com/?some-key=somevalue all --json
{"scheme":"https","hostname":"somedomain.com","port":"","path":"/","fragment":"","rawQuery":"some-key=somevalue","queryParams":[{"key":"some-key","value":"somevalue"}],"username":"","password":""}
```
## Contributors
Special thanks goes to all [contributors](https://github.com/thegeeklab/url-parser/graphs/contributors). If you would like to contribute,
please see the [instructions](https://github.com/thegeeklab/url-parser/blob/main/CONTRIBUTING.md).
Special thanks to all [contributors](https://github.com/thegeeklab/url-parser/graphs/contributors). If you would like to contribute, please see the [instructions](https://github.com/thegeeklab/url-parser/blob/main/CONTRIBUTING.md).
## License

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

@ -1,26 +1,126 @@
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"
)
// Version of current build
var Version = "devel"
//nolint:gochecknoglobals
var (
BuildVersion = "devel"
BuildDate = "00000000"
)
func main() {
app := cli.NewApp()
app.Name = "url-parser"
app.Usage = "Parse URL and shows the part of it."
app.Version = Version
app.Action = command.Run
app.Flags = globalFlags()
app.Commands = configCommands()
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)
}
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),
Flags: command.AllFlags(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

@ -1,8 +0,0 @@
// +build tools
package tools
import (
_ "golang.org/x/lint/golint"
_ "honnef.co/go/tools/cmd/staticcheck"
)

View File

@ -1,21 +0,0 @@
codecov:
require_ci_to_pass: true
coverage:
status:
project:
default:
target: auto
threshold: 5%
branches:
- main
if_ci_failed: error
informational: false
only_pulls: false
patch:
default:
target: auto
threshold: 5%
branches:
- main
if_ci_failed: error
only_pulls: false

109
command/commands.go Normal file
View File

@ -0,0 +1,109 @@
package command
import (
"net/url"
"strings"
"github.com/rs/zerolog/log"
"github.com/thegeeklab/url-parser/config"
)
type QueryParam struct {
Key string `json:"key"`
Value string `json:"value"`
}
type URL struct {
url *url.URL
Scheme string `json:"scheme"`
Hostname string `json:"hostname"`
Port string `json:"port"`
Path string `json:"path"`
Fragment string `json:"fragment"`
RawQuery string `json:"rawQuery"`
Query string `json:"-"`
QueryParams []QueryParam `json:"queryParams"`
Username string `json:"username"`
Password string `json:"password"`
}
func (u *URL) String() string {
return u.url.String()
}
type Parser struct {
URL string
QueryField string
QuerySplit bool
}
func NewURLParser(url, queryField string, querySplit bool) *Parser {
return &Parser{
URL: url,
QueryField: queryField,
QuerySplit: querySplit,
}
}
func (p *Parser) parse() *URL {
urlString := strings.TrimSpace(p.URL)
parts, err := url.Parse(urlString)
if err != nil {
log.Fatal().Err(err).Msg(config.ErrParseURL.Error())
}
extURL := &URL{
url: parts,
Scheme: parts.Scheme,
Hostname: parts.Hostname(),
Path: parts.Path,
Fragment: parts.Fragment,
QueryParams: []QueryParam{},
}
if len(parts.Scheme) > 0 {
extURL.Hostname = parts.Hostname()
extURL.Port = parts.Port()
}
if parts.User != nil {
if len(parts.User.Username()) > 0 {
extURL.Username = parts.User.Username()
}
}
if parts.User != nil {
pw, _ := parts.User.Password()
if len(pw) > 0 {
extURL.Password = pw
}
}
// Handle query field extraction
if parts.RawQuery != "" {
extURL.RawQuery = parts.RawQuery
}
if p.QueryField != "" {
if result := parts.Query().Get(p.QueryField); result != "" {
extURL.Query = result
}
} else {
extURL.Query = parts.RawQuery
}
// Handle query parameter splitting
values := parts.Query()
for k, v := range values {
if len(v) > 0 {
extURL.QueryParams = append(extURL.QueryParams, QueryParam{
Key: k,
Value: v[0],
})
}
}
return extURL
}

64
command/commands_test.go Normal file
View File

@ -0,0 +1,64 @@
package command
import (
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
)
func TestParse(t *testing.T) {
//nolint:goconst
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected *URL
}{
{
name: "parse url",
config: &config.Config{
URL: urlString,
QuerySplit: true,
},
expected: &URL{
Scheme: "postgres",
Username: "user",
Password: "pass",
Hostname: "host.com",
Port: "5432",
Path: "/path/to",
Query: "key=value&other=other%20value",
RawQuery: "key=value&other=other%20value",
QueryParams: []QueryParam{
{
Key: "key",
Value: "value",
},
{
Key: "other",
Value: "other value",
},
},
Fragment: "some-fragment",
},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := NewURLParser(urlString, "", false).parse()
assert.Equal(t, tt.expected.Scheme, result.Scheme)
assert.Equal(t, tt.expected.Username, result.Username)
assert.Equal(t, tt.expected.Password, result.Password)
assert.Equal(t, tt.expected.Hostname, result.Hostname)
assert.Equal(t, tt.expected.Port, result.Port)
assert.Equal(t, tt.expected.Path, result.Path)
assert.Equal(t, tt.expected.Fragment, result.Fragment)
assert.Equal(t, tt.expected.RawQuery, result.RawQuery)
assert.Equal(t, tt.expected.Query, result.Query)
assert.ElementsMatch(t, tt.expected.QueryParams, result.QueryParams)
})
}
}

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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if len(parts.Scheme) > 0 {
fmt.Println(parts.Fragment)
}
return nil
}
}

37
command/fragment_test.go Normal file
View File

@ -0,0 +1,37 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestFragment(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get fragment",
config: &config.Config{URL: urlString},
expected: "some-fragment",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Fragment(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if len(parts.Scheme) > 0 {
fmt.Println(parts.Hostname)
}
return nil
}
}

37
command/host_test.go Normal file
View File

@ -0,0 +1,37 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestHost(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get host",
config: &config.Config{URL: urlString},
expected: "host.com",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Host(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

21
command/password.go Normal file
View File

@ -0,0 +1,21 @@
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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if parts.Password != "" {
fmt.Println(parts.Password)
}
return nil
}
}

37
command/password_test.go Normal file
View File

@ -0,0 +1,37 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestPassword(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get password",
config: &config.Config{URL: urlString},
expected: "pass",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Password(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
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
}
}

42
command/path_test.go Normal file
View File

@ -0,0 +1,42 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestPath(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get path",
config: &config.Config{URL: urlString, PathIndex: -1},
expected: "/path/to",
},
{
name: "get path at index",
config: &config.Config{URL: urlString, PathIndex: 0},
expected: "path",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Path(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if len(parts.Scheme) > 0 {
fmt.Println(parts.Port)
}
return nil
}
}

37
command/port_test.go Normal file
View File

@ -0,0 +1,37 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestPort(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get port",
config: &config.Config{URL: urlString},
expected: "5432",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Port(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

33
command/query.go Normal file
View File

@ -0,0 +1,33 @@
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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if parts.Query != "" {
fmt.Println(parts.Query)
}
return nil
}
}

43
command/query_test.go Normal file
View File

@ -0,0 +1,43 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestQuery(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
QueryField string
expected string
}{
{
name: "get query",
config: &config.Config{URL: urlString},
expected: "key=value&other=other%20value",
},
{
name: "get query field",
config: &config.Config{URL: urlString, QueryField: "other"},
expected: "other value",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Query(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

39
command/run.go Normal file
View File

@ -0,0 +1,39 @@
package command
import (
"encoding/json"
"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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if len(parts.String()) > 0 {
if cfg.JSONOutput {
json, _ := json.Marshal(parts)
fmt.Println(string(json))
} else {
fmt.Println(parts)
}
}
return nil
}
}
// AllFlags defines flags for all subcommand.
func AllFlags(cfg *config.Config) []cli.Flag {
return []cli.Flag{
&cli.BoolFlag{
Name: "json",
Usage: "output json",
EnvVars: []string{"URL_PARSER_JSON"},
Destination: &cfg.JSONOutput,
},
}
}

88
command/run_test.go Normal file
View File

@ -0,0 +1,88 @@
package command
import (
"encoding/json"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestRun(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get url",
config: &config.Config{URL: urlString},
expected: urlString,
},
{
name: "get url with query split",
config: &config.Config{
URL: urlString,
QuerySplit: true,
JSONOutput: true,
},
expected: `{
"scheme": "postgres",
"hostname": "host.com",
"port": "5432",
"path": "/path/to",
"fragment": "some-fragment",
"rawQuery": "key=value&other=other%20value",
"queryParams": [
{
"key": "key",
"value": "value"
},
{
"key": "other",
"value": "other value"
}
],
"username": "user",
"password": "pass"
}`,
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Run(tt.config)(ctx) }))
if tt.config.JSONOutput {
got := &URL{}
expected := &URL{}
_ = json.Unmarshal([]byte(result), &got)
_ = json.Unmarshal([]byte(tt.expected), &expected)
assert.Equal(t, expected.Scheme, got.Scheme)
assert.Equal(t, expected.Username, got.Username)
assert.Equal(t, expected.Password, got.Password)
assert.Equal(t, expected.Hostname, got.Hostname)
assert.Equal(t, expected.Port, got.Port)
assert.Equal(t, expected.Path, got.Path)
assert.Equal(t, expected.Fragment, got.Fragment)
assert.Equal(t, expected.RawQuery, got.RawQuery)
assert.Equal(t, expected.Query, got.Query)
assert.ElementsMatch(t, expected.QueryParams, got.QueryParams)
return
}
assert.Equal(t, tt.expected, result)
})
}
}

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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if len(parts.Scheme) > 0 {
fmt.Println(parts.Scheme)
}
return nil
}
}

37
command/scheme_test.go Normal file
View File

@ -0,0 +1,37 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestScheme(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get scheme",
config: &config.Config{URL: urlString},
expected: "postgres",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = Scheme(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

21
command/user.go Normal file
View File

@ -0,0 +1,21 @@
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 := NewURLParser(cfg.URL, cfg.QueryField, cfg.QuerySplit).parse()
if parts.Username != "" {
fmt.Println(parts.Username)
}
return nil
}
}

37
command/user_test.go Normal file
View File

@ -0,0 +1,37 @@
package command
import (
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/thegeeklab/url-parser/config"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
func TestUser(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tests := []struct {
name string
config *config.Config
expected string
}{
{
name: "get user",
config: &config.Config{URL: urlString},
expected: "user",
},
}
for _, tt := range tests {
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
t.Run(tt.name, func(t *testing.T) {
result := strings.TrimSpace(capturer.CaptureStdout(func() { _ = User(tt.config)(ctx) }))
assert.Equal(t, tt.expected, result)
})
}
}

17
config/config.go Normal file
View File

@ -0,0 +1,17 @@
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
QuerySplit bool
PathIndex int
JSONOutput bool
}

25
go.mod
View File

@ -1,15 +1,22 @@
module github.com/thegeeklab/url-parser
go 1.16
go 1.23.3
require (
github.com/cpuguy83/go-md2man/v2 v2.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/sirupsen/logrus v1.8.1
github.com/urfave/cli/v2 v2.3.0
github.com/rs/zerolog v1.33.0
github.com/stretchr/testify v1.9.0
github.com/urfave/cli/v2 v2.27.5
github.com/zenizh/go-capturer v0.0.0-20211219060012-52ea6c8fed04
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616
golang.org/x/mod v0.4.2 // indirect
golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 // indirect
honnef.co/go/tools v0.2.2
)
require (
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 // indirect
golang.org/x/sys v0.12.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)

75
go.sum
View File

@ -1,58 +1,35 @@
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.0 h1:EoUDS0afbrsXAZ9YQ9jdu/mZ2sXgT1/2yyNng4PGlyM=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.5 h1:ZtcqGrnekaHpVLArFSe4HK5DoKx1T0rq2DwVB0alcyc=
github.com/cpuguy83/go-md2man/v2 v2.0.5/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
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/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/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
github.com/rs/zerolog v1.33.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/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/urfave/cli/v2 v2.3.0 h1:qph92Y649prgesehzOrQjdWyxFOp/QVM+6imKHad91M=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1 h1:gEOO8jv9F4OT7lGCjxCBTO/36wtF6j2nSip77qHd4x4=
github.com/xrash/smetrics v0.0.0-20240521201337-686a1a2994c1/go.mod h1:Ohn+xnUBiLI6FVj/9LpzZWtj1/D6lUovWYBkxHVV3aM=
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/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 h1:VLliZ0d+/avPrXXH+OakdXhpJuEoBZuwh1m2j7U6Iug=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096 h1:5PbJGn5Sp3GEUjJ61aYbUP6RIo3Z3r2E4Tv9y2z8UHo=
golang.org/x/sys v0.0.0-20210507161434-a76c4d0a0096/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
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=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
honnef.co/go/tools v0.2.2 h1:MNh1AVMyVX23VUHE2O27jm6lNj3vjO5DexS4A1xvnzk=
honnef.co/go/tools v0.2.2/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -1,19 +0,0 @@
package command
import (
"net/url"
"strings"
"github.com/sirupsen/logrus"
)
func parseURL(raw string) *url.URL {
urlString := strings.TrimSpace(raw)
url, err := url.Parse(urlString)
if err != nil {
logrus.Fatal(err)
}
return url
}

View File

@ -1,27 +0,0 @@
package command
import "testing"
type TestParseData struct {
urlString string
expected string
}
func TestParseURL(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestParseData{
{
urlString: urlString,
expected: urlString,
},
}
for _, table := range tables {
result := parseURL(urlString)
if result.String() != table.expected {
t.Fatalf("URL `%v`, should be `%v`", result, table.expected)
}
}
}

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,39 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestFragmentData struct {
urlString string
expected string
}
func TestFragment(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestFragmentData{
{
urlString: urlString,
expected: "some-fragment",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Fragment(c) }))
if result != table.expected {
t.Fatalf("URL fragment `%v`, should be `%v`", result, table.expected)
}
}
}

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,39 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestHostnameData struct {
urlString string
expected string
}
func TestHost(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestHostnameData{
{
urlString: urlString,
expected: "host.com",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Host(c) }))
if result != table.expected {
t.Fatalf("URL host `%v`, should be `%v`", result, table.expected)
}
}
}

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,39 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestPasswordData struct {
urlString string
expected string
}
func TestPassword(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestPasswordData{
{
urlString: urlString,
expected: "pass",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Password(c) }))
if result != table.expected {
t.Fatalf("URL password `%v`, should be `%v`", result, table.expected)
}
}
}

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 + 1; i < len(path) {
fmt.Println(path[i])
}
} else {
fmt.Println(parts.Path)
}
}
return nil
}

View File

@ -1,47 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestPathData struct {
urlString string
pathIndex int
expected string
}
func TestPath(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestPathData{
{
urlString: urlString,
pathIndex: -1,
expected: "/path/to",
},
{
urlString: 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")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Path(c) }))
if result != table.expected {
t.Fatalf("URL path `%v`, should be `%v`", result, table.expected)
}
}
}

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,39 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestPortData struct {
urlString string
expected string
}
func TestPort(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestPortData{
{
urlString: urlString,
expected: "5432",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Port(c) }))
if result != table.expected {
t.Fatalf("URL port `%v`, should be `%v`", result, table.expected)
}
}
}

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,46 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestQueryData struct {
urlString string
QueryField string
expected string
}
func TestQuery(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestQueryData{
{
urlString: urlString,
expected: "key=value&other=other%20value",
},
{
urlString: 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")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Query(c) }))
if result != table.expected {
t.Fatalf("URL query `%v`, should be `%v`", result, table.expected)
}
}
}

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,39 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestRunData struct {
urlString string
expected string
}
func TestRun(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestRunData{
{
urlString: urlString,
expected: urlString,
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Run(c) }))
if result != table.expected {
t.Fatalf("URL `%v`, should be `%v`", result, table.expected)
}
}
}

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,39 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestSchemeData struct {
urlString string
expected string
}
func TestScheme(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestSchemeData{
{
urlString: urlString,
expected: "postgres",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { Scheme(c) }))
if result != table.expected {
t.Fatalf("URL scheme `%v`, should be `%v`", result, table.expected)
}
}
}

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
}

View File

@ -1,39 +0,0 @@
package command
import (
"flag"
"strings"
"testing"
"github.com/urfave/cli/v2"
"github.com/zenizh/go-capturer"
)
type TestUserData struct {
urlString string
expected string
}
func TestUser(t *testing.T) {
urlString := "postgres://user:pass@host.com:5432/path/to?key=value&other=other%20value#some-fragment"
tables := []TestUserData{
{
urlString: urlString,
expected: "user",
},
}
for _, table := range tables {
app := cli.NewApp()
set := flag.NewFlagSet("test", 0)
set.String("url", table.urlString, "test url")
c := cli.NewContext(app, set, nil)
result := strings.TrimSpace(capturer.CaptureStdout(func() { User(c) }))
if result != table.expected {
t.Fatalf("URL user `%v`, should be `%v`", result, table.expected)
}
}
}