pl_fustigit 0.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +8 -0
- data/LICENSE +13 -0
- data/README.md +87 -0
- data/lib/pl_fustigit.rb +7 -0
- data/lib/uri/git.rb +23 -0
- data/lib/uri/rsync.rb +14 -0
- data/lib/uri/scp.rb +22 -0
- data/lib/uri/ssh.rb +22 -0
- data/lib/uri/triplets.rb +151 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b4505f60333c16eddbc339be71658e38554c9835652f13e9c120ac1e09618388
|
4
|
+
data.tar.gz: 4afdd2c689b1019d67dbd9d45f0a902922c485d1b01ffb3a6d73fb1d58a6a94b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 65d7c2a9980495c1961cc203955a535292d0376c974e1d60b8a7241f09f5d2e6b397fd1f2729868c3da7090a2d273c5c744b83432484abdbbe61c5c1f90a3952
|
7
|
+
data.tar.gz: d0bd11b5f845a28f6f1ce5f63c5a821081b8c1b6994eb42a2255e3c5c6158604954e616c0785ca5e6afe572ad9d7e3ee5a6e88e3c3a0c3151ba165b15ec3e0ce
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,8 @@
|
|
1
|
+
## Changelog
|
2
|
+
All notable changes to this project will be documented in this file.
|
3
|
+
This project attempts to adhere to [Semantic Versioning](http://semver.org/).
|
4
|
+
This changelog attempts to adhere to [Keep a CHANGELOG](http://keepachangelog.com/).
|
5
|
+
|
6
|
+
## [0.5.0] - 21 February 2024
|
7
|
+
### Changed
|
8
|
+
- Forked from mckern/fustigit; hopefully as a temporary measure.
|
data/LICENSE
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
Copyright 2014-2022 Ryan McKern
|
2
|
+
|
3
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
4
|
+
you may not use this file except in compliance with the License.
|
5
|
+
You may obtain a copy of the License at
|
6
|
+
|
7
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
8
|
+
|
9
|
+
Unless required by applicable law or agreed to in writing, software
|
10
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
11
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
12
|
+
See the License for the specific language governing permissions and
|
13
|
+
limitations under the License.
|
data/README.md
ADDED
@@ -0,0 +1,87 @@
|
|
1
|
+
## Fustigit: gorram Git addresses
|
2
|
+
|
3
|
+
<dl>
|
4
|
+
<dt>Fustigate — (verb) fus·ti·gate </dd>
|
5
|
+
<dd>To beat with a club; cudgel.</dd>
|
6
|
+
<dd>To criticize harshly.</dd>
|
7
|
+
</dl>
|
8
|
+
|
9
|
+
[](https://github.com/mckern/fustigit/actions/workflows/tests.yaml)
|
10
|
+
[](https://badge.fury.io/rb/fustigit)
|
11
|
+
|
12
|
+
### TL;DR
|
13
|
+
|
14
|
+
Fustigit will let you "parse" SCP-like address triplets using Ruby's baked-in [URI library](https://ruby-doc.org/stdlib-2.5.7/libdoc/uri/rdoc/index.html) (... and just a *moderate* amount of monkey-patching) and turn them into probably-valid URI objects.
|
15
|
+
|
16
|
+
### What's a Triplet?
|
17
|
+
|
18
|
+
<a href="https://www.debuggex.com/r/NtHqyDI9LUz-UMia"><img src="readme/railroad-diagram.jpg"></a>
|
19
|
+
|
20
|
+
A triplet is a format for specifying a remote resource, much like a URI. It looks like this:
|
21
|
+
|
22
|
+
# The username is optional but the hostname and pathname are not
|
23
|
+
<username>@<hostname>:<pathname>
|
24
|
+
|
25
|
+
Triplets predate the [original ratification of the URI RFC](https://tools.ietf.org/html/rfc2396), and are *tricksy* to parse if you're playing by URI rules since they don't define a protocol and they use a colon to separate the hostname from the pathname. `scp` and `git` are the two most common tools that still use triplets.
|
26
|
+
|
27
|
+
### Why would I need to parse triplets?
|
28
|
+
|
29
|
+
The answer is usually "[Git](https://git-scm.com)" (but sometimes it's `scp`). Git supports a conveniently inconvenient number of formats for expressing where a remote repository is located and/or what protocol should be used to connect to it. Some of them are perfectly valid URIs. Some of them are not. It's the ones that are not that may be a problem.
|
30
|
+
|
31
|
+
```yaml
|
32
|
+
---
|
33
|
+
# These won't parse and they're both SUPER common
|
34
|
+
- example.com:path/to/repo.git
|
35
|
+
- git@example.com:user/project.git
|
36
|
+
|
37
|
+
# But these will parse, which is great since they're also SUPER common
|
38
|
+
- https://example.com/user/project.git
|
39
|
+
- http://example.com/user/project.git
|
40
|
+
```
|
41
|
+
|
42
|
+
Enter Fustigit.
|
43
|
+
|
44
|
+
### How (do I use this)?
|
45
|
+
|
46
|
+
<s>Carelessly</s> Without a care in the world!
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
>> URI.parse "git@github.com:mckern/fustigit.git"
|
50
|
+
URI::InvalidURIError: bad URI(is not URI?): git@github.com:mckern/fustigit.git [/some/path/for/ruby/lib/ruby/2.1.0/uri/common.rb:176:in `split']
|
51
|
+
>> require 'fustigit'
|
52
|
+
=> true
|
53
|
+
>> uri = URI.parse "git@github.com:mckern/fustigit.git"
|
54
|
+
=> #<URI::SSH:0x007f8459131f98 URL:git@github.com:mckern/fustigit.git>
|
55
|
+
>> uri.host
|
56
|
+
=> "github.com"
|
57
|
+
>> uri.user
|
58
|
+
=> "git"
|
59
|
+
>> uri.path
|
60
|
+
=> "mckern/fustigit.git"
|
61
|
+
>> uri.to_s
|
62
|
+
=> "git@github.com:mckern/fustigit.git"
|
63
|
+
>>
|
64
|
+
```
|
65
|
+
|
66
|
+
### How (does it work)?
|
67
|
+
|
68
|
+
Careful use of `Module#prepend` and `Module#extend` in `URI` and `URI::Parser`, judicious use of regular expressions, and by defining a few new `URI` subclasses: `URI::Git`, `URI::SSH`, `URI::SCP`, and `URI::RSYNC`. Some of these classes then have the `Triplet` module mixed in, which helps smooth over the conversion between a valid RFC-compliant URI and an address triplet.
|
69
|
+
|
70
|
+
### What if I'm using `Addressable::URI` instead of `::URI`?
|
71
|
+
|
72
|
+
Take a look at Martin Emde's [Gitable](https://github.com/martinemde/gitable), which extends `Addressable::URI` with additional support for Git addresses.
|
73
|
+
|
74
|
+
### Support & contribution?
|
75
|
+
|
76
|
+
In the spirit of Jordan Sissel (a hero to admins and operations people everywhere), if fustigit is not helping you parse weird Git addresses, then there is a bug in fustigit. Please open an issue or submit a pull request if something doesn't work.
|
77
|
+
|
78
|
+
### License
|
79
|
+
|
80
|
+
Fustigate is licensed under the Apache License, Version 2.0.
|
81
|
+
|
82
|
+
> "When in doubt, use brute force."
|
83
|
+
> ― <cite>Ken Thompson</cite>
|
84
|
+
|
85
|
+
### Maintainer
|
86
|
+
|
87
|
+
Ryan McKern <ryan@mckern.sh>
|
data/lib/pl_fustigit.rb
ADDED
data/lib/uri/git.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri/generic"
|
4
|
+
|
5
|
+
module URI
|
6
|
+
class Git < Generic
|
7
|
+
include Triplets
|
8
|
+
|
9
|
+
DEFAULT_PORT = 9418
|
10
|
+
USE_REGISTRY = false
|
11
|
+
|
12
|
+
COMPONENT = %i[
|
13
|
+
scheme
|
14
|
+
userinfo
|
15
|
+
host port path
|
16
|
+
].freeze
|
17
|
+
end
|
18
|
+
if respond_to? :register_scheme
|
19
|
+
register_scheme "GIT", Git
|
20
|
+
else
|
21
|
+
@@schemes["GIT"] = Git
|
22
|
+
end
|
23
|
+
end
|
data/lib/uri/rsync.rb
ADDED
data/lib/uri/scp.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri/generic"
|
4
|
+
|
5
|
+
module URI
|
6
|
+
class SCP < Generic
|
7
|
+
include Triplets
|
8
|
+
|
9
|
+
DEFAULT_PORT = 22
|
10
|
+
|
11
|
+
COMPONENT = %i[
|
12
|
+
scheme
|
13
|
+
userinfo
|
14
|
+
host port path
|
15
|
+
].freeze
|
16
|
+
end
|
17
|
+
if respond_to? :register_scheme
|
18
|
+
register_scheme "SCP", SCP
|
19
|
+
else
|
20
|
+
@@schemes["SCP"] = SCP
|
21
|
+
end
|
22
|
+
end
|
data/lib/uri/ssh.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri/generic"
|
4
|
+
|
5
|
+
module URI
|
6
|
+
class SSH < Generic
|
7
|
+
include Triplets
|
8
|
+
|
9
|
+
DEFAULT_PORT = 22
|
10
|
+
|
11
|
+
COMPONENT = %i[
|
12
|
+
scheme
|
13
|
+
userinfo
|
14
|
+
host port path
|
15
|
+
].freeze
|
16
|
+
end
|
17
|
+
if respond_to? :register_scheme
|
18
|
+
register_scheme "SSH", SSH
|
19
|
+
else
|
20
|
+
@@schemes["SSH"] = SSH
|
21
|
+
end
|
22
|
+
end
|
data/lib/uri/triplets.rb
ADDED
@@ -0,0 +1,151 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
|
5
|
+
# Triplets is a mix-in for subclasses of URI::Generic, which
|
6
|
+
# allows URI to use SCP-style Triplet URLs in a somewhat more
|
7
|
+
# meaningful way.
|
8
|
+
module Triplets
|
9
|
+
attr_accessor :scheme, :user, :host, :path
|
10
|
+
|
11
|
+
# @return [String] a string representation of the URI components
|
12
|
+
# as an SCP-style Triplet
|
13
|
+
def triplet
|
14
|
+
str = []
|
15
|
+
str << "#{user}@" if user && !user.empty?
|
16
|
+
str << "#{host}:#{path}".squeeze("/")
|
17
|
+
str.join
|
18
|
+
end
|
19
|
+
private :triplet
|
20
|
+
|
21
|
+
# @return [String] a string representation of the URI components
|
22
|
+
# as a valid RFC compliant URI
|
23
|
+
# rubocop:disable Metrics/AbcSize
|
24
|
+
def rfc_uri
|
25
|
+
str = []
|
26
|
+
str << "#{scheme}://" if scheme
|
27
|
+
str << "#{user}@" if user
|
28
|
+
if port && port != self.class::DEFAULT_PORT
|
29
|
+
host_info = [host, port].join(":")
|
30
|
+
str << [host_info, path].join("/").squeeze("/")
|
31
|
+
else
|
32
|
+
str << [host, path].join("/").squeeze("/")
|
33
|
+
end
|
34
|
+
str.join
|
35
|
+
end
|
36
|
+
private :rfc_uri
|
37
|
+
# rubocop:enable Metrics/AbcSize
|
38
|
+
|
39
|
+
def to_s
|
40
|
+
return triplet if triplet?
|
41
|
+
|
42
|
+
rfc_uri
|
43
|
+
end
|
44
|
+
|
45
|
+
# Use the same regular expressions that the parser uses to determine
|
46
|
+
# if this is a valid triplet.
|
47
|
+
def triplet?
|
48
|
+
# False if self matches a normal URI scheme
|
49
|
+
rfc_uri !~ URI.parser.const_get(:TI_SCHEME) &&
|
50
|
+
# False unless self matches a Triplet scheme
|
51
|
+
!!(triplet =~ URI.parser.const_get(:TI_TRIPLET))
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# A SCP Triplet is *not* a canonical URI. It doesn't follow any RFCs that
|
56
|
+
# I've been able to find, and it's difficult to reason about if you
|
57
|
+
# try to force it into a URI::Generic as-is. TripletInterruptus provides
|
58
|
+
# helper methods that preserve the upstream behavior of URI::Generic
|
59
|
+
# but extend it just enough that it doesn't choke on SCP Triplets if
|
60
|
+
# they're passed.
|
61
|
+
module TripletInterruptus
|
62
|
+
# Determine if a string can be teased apart into URI-like components
|
63
|
+
TI_TRIPLET = %r{\A(?:(?<userinfo>.+)@+)?(?<host>[\w.-]+):(?<path>.*)\z}
|
64
|
+
|
65
|
+
# Determine if a string is prefixed with a URI scheme like http:// or ssh://
|
66
|
+
TI_SCHEME = %r{\A(?:(?<scheme>[a-z]+)://)}
|
67
|
+
|
68
|
+
def parse(uri)
|
69
|
+
return build_triplet(uri) if triplet?(uri)
|
70
|
+
|
71
|
+
super(uri)
|
72
|
+
end
|
73
|
+
|
74
|
+
def split(uri)
|
75
|
+
return super(uri) unless triplet?(uri)
|
76
|
+
|
77
|
+
parts = parse_triplet(uri)
|
78
|
+
[nil, parts[:userinfo], parts[:host], nil,
|
79
|
+
nil, parts[:path], nil, nil, nil]
|
80
|
+
end
|
81
|
+
|
82
|
+
def triplet?(address)
|
83
|
+
address.match(TI_TRIPLET) && !address.match(TI_SCHEME)
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_triplet(address)
|
87
|
+
values = parse_triplet(address)
|
88
|
+
return nil unless values
|
89
|
+
|
90
|
+
URI.scheme_list[URI.default_triplet_type].build(values)
|
91
|
+
end
|
92
|
+
private :build_triplet
|
93
|
+
|
94
|
+
def parse_triplet(address)
|
95
|
+
parts = address.match(TI_TRIPLET)
|
96
|
+
return nil unless parts
|
97
|
+
|
98
|
+
parts.names.map(&:to_sym).zip(parts.captures).to_h
|
99
|
+
end
|
100
|
+
private :parse_triplet
|
101
|
+
end
|
102
|
+
|
103
|
+
module TripletHandling
|
104
|
+
TRIPLET_CLASSES = %w[Git SCP SSH].freeze
|
105
|
+
|
106
|
+
def self.included(base)
|
107
|
+
base.extend(TripletHandling)
|
108
|
+
end
|
109
|
+
|
110
|
+
def default_triplet_type
|
111
|
+
@default_triplet_type ||= "SSH"
|
112
|
+
end
|
113
|
+
|
114
|
+
def default_triplet_type=(value)
|
115
|
+
raise ArgumentError, "'#{value}' is not one of: #{TRIPLET_CLASSES.join(', ')}" unless TRIPLET_CLASSES.include?(value)
|
116
|
+
|
117
|
+
@default_triplet_type = value
|
118
|
+
end
|
119
|
+
|
120
|
+
def parser
|
121
|
+
return URI::RFC3986_Parser if
|
122
|
+
Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.2.0")
|
123
|
+
|
124
|
+
URI::Parser
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# Reopen URI and include TripletHandling (which will then
|
129
|
+
# extend URI to add triplet-specific class methods).
|
130
|
+
module URI
|
131
|
+
include TripletHandling
|
132
|
+
end
|
133
|
+
|
134
|
+
module URI
|
135
|
+
# Reopen URI::Parser and prepend TripletInterruptus. This
|
136
|
+
# allows us to hook into URI::Parser.parse and attempt to
|
137
|
+
# parse a triplet before URI::Parser can reject it. Otherwise
|
138
|
+
# fall through to the original URI::Parser.parse method.
|
139
|
+
#
|
140
|
+
if Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.2.0")
|
141
|
+
# rubocop:disable Naming/ClassAndModuleCamelCase
|
142
|
+
class RFC3986_Parser
|
143
|
+
prepend TripletInterruptus
|
144
|
+
end
|
145
|
+
# rubocop:enable Naming/ClassAndModuleCamelCase
|
146
|
+
else
|
147
|
+
class Parser
|
148
|
+
prepend TripletInterruptus
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pl_fustigit
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.5.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan McKern
|
8
|
+
- Puppet Release Engineering
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2024-02-21 00:00:00.000000000 Z
|
13
|
+
dependencies: []
|
14
|
+
description: |
|
15
|
+
Forked from mckern/fustigit, it will "Parse" SCP-like address triplets with the standard
|
16
|
+
Ruby URI Library.
|
17
|
+
email: release@puppet.com
|
18
|
+
executables: []
|
19
|
+
extensions: []
|
20
|
+
extra_rdoc_files: []
|
21
|
+
files:
|
22
|
+
- CHANGELOG.md
|
23
|
+
- LICENSE
|
24
|
+
- README.md
|
25
|
+
- lib/pl_fustigit.rb
|
26
|
+
- lib/uri/git.rb
|
27
|
+
- lib/uri/rsync.rb
|
28
|
+
- lib/uri/scp.rb
|
29
|
+
- lib/uri/ssh.rb
|
30
|
+
- lib/uri/triplets.rb
|
31
|
+
homepage: http://github.com/puppetlabs/pl_fustigit
|
32
|
+
licenses:
|
33
|
+
- Apache-2.0
|
34
|
+
metadata: {}
|
35
|
+
post_install_message:
|
36
|
+
rdoc_options: []
|
37
|
+
require_paths:
|
38
|
+
- lib
|
39
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 3.0.0
|
44
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - ">="
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
requirements: []
|
50
|
+
rubygems_version: 3.0.3
|
51
|
+
signing_key:
|
52
|
+
specification_version: 4
|
53
|
+
summary: Use URI to "parse" SCP-like triplets
|
54
|
+
test_files: []
|