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 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 &#8212; (verb) fus&middot;ti&middot;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
+ > &#8213; <cite>Ken Thompson</cite>
84
+
85
+ ### Maintainer
86
+
87
+ Ryan McKern &lt;ryan@mckern.sh&gt;
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri/triplets"
4
+ require "uri/git"
5
+ require "uri/scp"
6
+ require "uri/ssh"
7
+ require "uri/rsync"
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
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "uri/generic"
4
+
5
+ module URI
6
+ class RSYNC < Generic
7
+ DEFAULT_PORT = 873
8
+ end
9
+ if respond_to? :register_scheme
10
+ register_scheme "RSYNC", RSYNC
11
+ else
12
+ @@schemes["RSYNC"] = RSYNC
13
+ end
14
+ end
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
@@ -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: []