pl_fustigit 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
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: []