pl_fustigit 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Test & Lint](https://github.com/mckern/fustigit/actions/workflows/tests.yaml/badge.svg)](https://github.com/mckern/fustigit/actions/workflows/tests.yaml)
|
10
|
+
[![Gem Version](https://badge.fury.io/rb/fustigit.svg)](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: []
|