gistribute 0.2 → 0.3
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 +4 -4
- data/.github/workflows/blocking-issues.yml +14 -0
- data/.github/workflows/lint.yml +17 -0
- data/.github/workflows/test.yml +21 -0
- data/.gitignore +21 -0
- data/.rubocop.yml +94 -0
- data/Gemfile +4 -0
- data/README.md +32 -23
- data/Rakefile +2 -0
- data/VERSION +1 -1
- data/bin/gistribute +3 -83
- data/gistribute.gemspec +14 -7
- data/lib/cli/auth.rb +64 -0
- data/lib/cli/install.rb +86 -0
- data/lib/cli/upload.rb +54 -0
- data/lib/cli.rb +117 -0
- data/lib/gistribute.rb +33 -0
- data/spec/.rubocop.yml +46 -0
- data/spec/gistribute/cli_auth_spec.rb +133 -0
- data/spec/gistribute/cli_install_spec.rb +193 -0
- data/spec/gistribute/cli_spec.rb +31 -0
- data/spec/gistribute/cli_upload_spec.rb +161 -0
- data/spec/gistribute_spec.rb +15 -27
- data/spec/spec_helper.rb +40 -0
- data/spec/support/cli.rb +27 -0
- data/spec/support/constants.rb +4 -0
- metadata +123 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54d0c1a3f95efadf4af148ba00f9c52f66bc80b4f979d357a7430c5c412e96ab
|
4
|
+
data.tar.gz: 49fafdc9abd4ba1d994f796cf047c925159ee3d9bf9128386a8e3341fff04194
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 4d01816a4228bf6041d1b6753b77655ce613166e4bdc8772a9d2e8482d1031fde7b3607c9664ccbd855b85d4e84ed82805dec1401f9d7a9c99af75fdd7991e4a
|
7
|
+
data.tar.gz: 83041e56c9d92034509149eb5a1968cdfea92dba1b15d3d66751b3597d2c602940e078a9eed2af3fd92f191cc9a05d9ad41687be5538180c9180c2bf53bef08e
|
@@ -0,0 +1,14 @@
|
|
1
|
+
name: Blocking Issues
|
2
|
+
|
3
|
+
on:
|
4
|
+
issues:
|
5
|
+
types: [opened, edited, deleted, transferred, closed, reopened]
|
6
|
+
pull_request_target:
|
7
|
+
types: [opened, edited, closed, reopened]
|
8
|
+
|
9
|
+
jobs:
|
10
|
+
blocking_issues:
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
name: Check for blocking issues
|
13
|
+
steps:
|
14
|
+
- uses: Levi-Lesches/blocking-issues@v2
|
@@ -0,0 +1,17 @@
|
|
1
|
+
on: [push, pull_request]
|
2
|
+
|
3
|
+
name: Lint
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
lint:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
steps:
|
9
|
+
- name: Checkout repository
|
10
|
+
uses: actions/checkout@v3
|
11
|
+
- name: Set up Ruby
|
12
|
+
uses: ruby/setup-ruby@v1
|
13
|
+
with:
|
14
|
+
ruby-version: 3.2
|
15
|
+
bundler-cache: true
|
16
|
+
- name: Run RuboCop
|
17
|
+
run: bundle exec rubocop
|
@@ -0,0 +1,21 @@
|
|
1
|
+
on: [push, pull_request]
|
2
|
+
|
3
|
+
name: Test
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
test:
|
7
|
+
runs-on: ubuntu-latest
|
8
|
+
env:
|
9
|
+
GISTRIBUTE_TEST_OAUTH_TOKEN: ${{ secrets.GISTRIBUTE_TEST_OAUTH_TOKEN }}
|
10
|
+
steps:
|
11
|
+
- name: Checkout repository
|
12
|
+
uses: actions/checkout@v3
|
13
|
+
- name: Set up Ruby
|
14
|
+
uses: ruby/setup-ruby@v1
|
15
|
+
with:
|
16
|
+
ruby-version: 3.2
|
17
|
+
bundler-cache: true
|
18
|
+
- name: Check for focused tests
|
19
|
+
run: bundle exec rubocop --only RSpec/Focus
|
20
|
+
- name: Run tests
|
21
|
+
run: bundle exec rspec --format doc
|
data/.gitignore
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
*.gem
|
2
|
+
*.rbc
|
3
|
+
.bundle
|
4
|
+
.config
|
5
|
+
coverage
|
6
|
+
InstalledFiles
|
7
|
+
lib/bundler/man
|
8
|
+
pkg
|
9
|
+
rdoc
|
10
|
+
spec/reports
|
11
|
+
test/tmp
|
12
|
+
test/version_tmp
|
13
|
+
tmp
|
14
|
+
|
15
|
+
# YARD artifacts
|
16
|
+
.yardoc
|
17
|
+
_yardoc
|
18
|
+
doc/
|
19
|
+
|
20
|
+
# Don't push Gemfile.lock on a RubyGem
|
21
|
+
Gemfile.lock
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require:
|
2
|
+
- rubocop-rspec
|
3
|
+
|
4
|
+
AllCops:
|
5
|
+
NewCops: enable
|
6
|
+
TargetRubyVersion: 3.2
|
7
|
+
|
8
|
+
Gemspec/DevelopmentDependencies:
|
9
|
+
EnforcedStyle: gemspec
|
10
|
+
|
11
|
+
Gemspec/RequiredRubyVersion:
|
12
|
+
Enabled: false
|
13
|
+
|
14
|
+
Layout/ArgumentAlignment:
|
15
|
+
Enabled: false
|
16
|
+
|
17
|
+
Layout/EndAlignment:
|
18
|
+
EnforcedStyleAlignWith: variable
|
19
|
+
|
20
|
+
Layout/ExtraSpacing:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Layout/FirstHashElementIndentation:
|
24
|
+
EnforcedStyle: consistent
|
25
|
+
|
26
|
+
Layout/MultilineMethodCallIndentation:
|
27
|
+
EnforcedStyle: indented
|
28
|
+
|
29
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
30
|
+
Enabled: false
|
31
|
+
|
32
|
+
Layout/TrailingWhitespace:
|
33
|
+
AllowInHeredoc: false
|
34
|
+
|
35
|
+
Lint/NonDeterministicRequireOrder:
|
36
|
+
Enabled: false
|
37
|
+
|
38
|
+
Metrics:
|
39
|
+
Enabled: false
|
40
|
+
|
41
|
+
Naming/HeredocDelimiterNaming:
|
42
|
+
Enabled: false
|
43
|
+
|
44
|
+
Naming/MethodParameterName:
|
45
|
+
Enabled: false
|
46
|
+
|
47
|
+
Naming/VariableNumber:
|
48
|
+
Enabled: false
|
49
|
+
|
50
|
+
Security/Eval:
|
51
|
+
Exclude:
|
52
|
+
- lib/cli.rb
|
53
|
+
|
54
|
+
Style/ClassAndModuleChildren:
|
55
|
+
Enabled: false
|
56
|
+
|
57
|
+
Style/Documentation:
|
58
|
+
Enabled: false
|
59
|
+
|
60
|
+
Style/FormatString:
|
61
|
+
Enabled: false
|
62
|
+
|
63
|
+
Style/GuardClause:
|
64
|
+
Enabled: false
|
65
|
+
|
66
|
+
Style/IfUnlessModifier:
|
67
|
+
Enabled: false
|
68
|
+
|
69
|
+
Style/MultilineTernaryOperator:
|
70
|
+
Enabled: false
|
71
|
+
|
72
|
+
Style/NestedParenthesizedCalls:
|
73
|
+
Enabled: false
|
74
|
+
|
75
|
+
Style/NestedTernaryOperator:
|
76
|
+
Enabled: false
|
77
|
+
|
78
|
+
Style/Next:
|
79
|
+
Enabled: false
|
80
|
+
|
81
|
+
Style/NumericPredicate:
|
82
|
+
Enabled: false
|
83
|
+
|
84
|
+
Style/ParallelAssignment:
|
85
|
+
Enabled: false
|
86
|
+
|
87
|
+
Style/RequireOrder:
|
88
|
+
Enabled: true
|
89
|
+
|
90
|
+
Style/StderrPuts:
|
91
|
+
Enabled: false
|
92
|
+
|
93
|
+
Style/StringLiterals:
|
94
|
+
EnforcedStyle: double_quotes
|
data/Gemfile
ADDED
data/README.md
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
#
|
1
|
+
# gistribute
|
2
2
|
|
3
|
-
|
3
|
+
gistribute is a simple file distribution system based on [GitHub
|
4
|
+
Gists](https://gist.github.com/).
|
4
5
|
|
5
|
-
I decided to make
|
6
|
+
I decided to make gistribute when I found myself sharing configuration files
|
6
7
|
and such with others by placing all of them into a Gist along with a little
|
7
|
-
Bash script that
|
8
|
-
location on the other's computer. This program
|
9
|
-
script, and the need to update the raw URLs in that script whenever you
|
10
|
-
a
|
8
|
+
Bash script that `curl`ed all of the files, via their raw URLs, to the right
|
9
|
+
location on the other's computer. This program removes the need to make that
|
10
|
+
script, and the need to update the raw URLs in that script whenever you edit
|
11
|
+
a file in the Gist.
|
11
12
|
|
12
13
|
## Installation
|
13
14
|
|
@@ -17,30 +18,38 @@ gem install gistribute
|
|
17
18
|
|
18
19
|
## How It Works
|
19
20
|
|
20
|
-
|
21
|
+
gistribute looks at the filename that you enter on Gist to find all of the
|
21
22
|
data that it needs to download the file to the other user's computer. It
|
22
|
-
allows you to choose what
|
23
|
+
allows you to choose what gistribute will call the file when it is installing
|
23
24
|
it, and where it will install the file.
|
24
25
|
|
25
|
-
|
26
|
-
|
27
|
-
If, for example, you were sharing a .vimrc file, and you wanted Gistribute to
|
26
|
+
If, for example, you were sharing a `~/.vimrc` file, and you wanted gistribute to
|
28
27
|
call it "Vim configuration" when it was installing it, you would name the file
|
29
|
-
`Vim configuration
|
28
|
+
`Vim configuration || ~|.vimrc`. If the filename contains the sequence `||`,
|
30
29
|
anything before that will be considered the description of that file, and
|
31
|
-
anything after it the installation path. If there is no `||`,
|
30
|
+
anything after it the installation path. If there is no `||`, gistribute will
|
32
31
|
use the name of the file (without the path to it) as the default description.
|
33
32
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
33
|
+
## Usage
|
34
|
+
|
35
|
+
### Uploads
|
36
|
+
|
37
|
+
To upload a gistribution, use the `upload` subcommand and pass in as many files
|
38
|
+
or directories as you would like. Directories will be recursively processed and
|
39
|
+
uploaded. The install paths will be the same ones that were used on your
|
40
|
+
system. The home directory will be handled automatically.
|
41
|
+
|
42
|
+
```sh
|
43
|
+
gistribute upload ~/.bashrc ~/.bash_profile
|
44
|
+
```
|
45
|
+
|
46
|
+
### Downloads
|
38
47
|
|
39
|
-
If the resulting Gist link was, for example, https://gist.github.com/123456
|
40
|
-
the
|
41
|
-
to `~/.
|
48
|
+
If the resulting Gist link was, for example, `https://gist.github.com/user/123456`,
|
49
|
+
the receiver would be able to run either of these commands to download the files
|
50
|
+
to `~/.bashrc` and `~/.bash_profile`:
|
42
51
|
|
43
52
|
```sh
|
44
|
-
gistribute 123456
|
45
|
-
gistribute https://gist.github.com/123456
|
53
|
+
gistribute install 123456
|
54
|
+
gistribute install https://gist.github.com/user/123456
|
46
55
|
```
|
data/Rakefile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3
|
data/bin/gistribute
CHANGED
@@ -1,86 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
+
# frozen_string_literal: true
|
2
3
|
|
3
|
-
require "
|
4
|
-
require "fileutils"
|
5
|
-
require "json"
|
6
|
-
require "open-uri"
|
4
|
+
require "gistribute"
|
7
5
|
|
8
|
-
|
9
|
-
CLEAR = "\r\e[K"
|
10
|
-
|
11
|
-
if %w[-v --version].include? ARGV.first
|
12
|
-
puts "Gistribute #{File.read(File.expand_path("../../VERSION", __FILE__)).strip}"
|
13
|
-
exit 0
|
14
|
-
end
|
15
|
-
|
16
|
-
print "Downloading data..."
|
17
|
-
|
18
|
-
# The user can pass in either just the ID or the entire URL to the Gist.
|
19
|
-
id = ARGV.first[/(^|\/)([[:xdigit:]]+)/, 2]
|
20
|
-
|
21
|
-
begin
|
22
|
-
gist = JSON.parse(URI.open("https://api.github.com/gists/#{id}").read)
|
23
|
-
rescue OpenURI::HTTPError => msg
|
24
|
-
print <<~EOS.red
|
25
|
-
#{CLEAR}There was an error downloading the requested Gist.
|
26
|
-
The error is as follows:
|
27
|
-
EOS
|
28
|
-
puts msg
|
29
|
-
|
30
|
-
puts "The ID that was queried is:".red
|
31
|
-
puts id
|
32
|
-
|
33
|
-
exit -1
|
34
|
-
end
|
35
|
-
|
36
|
-
# The JSON data contains a lot of information. The information that is
|
37
|
-
# relevant to this program is as follows:
|
38
|
-
#
|
39
|
-
# {
|
40
|
-
# "html_url" => "Link to the Gist",
|
41
|
-
# "description" => "The description for the Gist",
|
42
|
-
#
|
43
|
-
# "owner" => nil, # IF ANONYMOUS
|
44
|
-
# "owner" => { # IF TIED TO A USER
|
45
|
-
# "login" => "username"
|
46
|
-
# },
|
47
|
-
#
|
48
|
-
# "files" => {
|
49
|
-
# "filename of first file" => {
|
50
|
-
# "content" => "entire contents of the file"
|
51
|
-
# }
|
52
|
-
# # Repeat the above for every file in the Gist.
|
53
|
-
# }
|
54
|
-
# }
|
55
|
-
|
56
|
-
# Regular expression word wrap to keep lines less than 80 characters. Then
|
57
|
-
# check to see if it's empty- if not, put newlines on each side so that it
|
58
|
-
# will be padded when displayed in the output.
|
59
|
-
desc = gist["description"].gsub(/(.{1,79})(\s+|\Z)/, "\\1\n").strip
|
60
|
-
desc = "\n#{desc}\n" unless desc.empty?
|
61
|
-
|
62
|
-
puts <<~EOS
|
63
|
-
#{CLEAR}Finished downloading Gist from: #{gist["html_url"]}
|
64
|
-
Gist uploaded by #{
|
65
|
-
gist["owner"] ? "user #{gist["owner"]["login"]}" : "an anonymous user"
|
66
|
-
}.
|
67
|
-
#{desc}
|
68
|
-
Beginning install...
|
69
|
-
EOS
|
70
|
-
|
71
|
-
gist["files"].each do |filename, data|
|
72
|
-
metadata = filename.split("||").map &:strip
|
73
|
-
|
74
|
-
# | as path separator in the Gist's file name, as Gist doesn't allow the
|
75
|
-
# usage of /.
|
76
|
-
path = metadata.last.gsub(/[~|]/, "|" => "/", "~" => Dir.home)
|
77
|
-
# Default description is the name of the file.
|
78
|
-
description = metadata.size == 1 ? File.basename(path) : metadata.first
|
79
|
-
|
80
|
-
puts " #{"*".green} Installing #{description}..."
|
81
|
-
|
82
|
-
# Handle directories that don't exist.
|
83
|
-
FileUtils.mkdir_p File.dirname(path)
|
84
|
-
|
85
|
-
File.write(path, data["content"])
|
86
|
-
end
|
6
|
+
Gistribute::CLI.new.run
|
data/gistribute.gemspec
CHANGED
@@ -1,10 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
Gem::Specification.new do |gem|
|
2
4
|
gem.name = "gistribute"
|
3
|
-
gem.version = File.read(File.expand_path("
|
5
|
+
gem.version = File.read(File.expand_path("VERSION", __dir__)).strip
|
4
6
|
|
5
7
|
gem.author = "Vinny Diehl"
|
6
8
|
gem.email = "vinny.diehl@gmail.com"
|
7
|
-
gem.homepage = "https://github.com/
|
9
|
+
gem.homepage = "https://github.com/vinnydiehl/gistribute"
|
10
|
+
gem.metadata["rubygems_mfa_required"] = "true"
|
8
11
|
|
9
12
|
gem.license = "MIT"
|
10
13
|
|
@@ -13,13 +16,17 @@ Gem::Specification.new do |gem|
|
|
13
16
|
|
14
17
|
gem.bindir = "bin"
|
15
18
|
gem.executables = %w[gistribute]
|
16
|
-
|
17
|
-
gem.test_files = Dir["spec/**/*"]
|
18
|
-
gem.files = Dir["bin/**/*"] + gem.test_files + %w[
|
19
|
-
LICENSE Rakefile README.md VERSION gistribute.gemspec
|
20
|
-
]
|
19
|
+
gem.files = `git ls-files -z`.split "\x0"
|
21
20
|
|
22
21
|
gem.add_dependency "colorize", "~> 1.0"
|
22
|
+
gem.add_dependency "faraday-retry", "~> 2.2"
|
23
|
+
gem.add_dependency "launchy", "~> 2.5"
|
24
|
+
gem.add_dependency "octokit", "~> 6.1"
|
25
|
+
gem.add_dependency "optimist_xl", "~> 3.3"
|
26
|
+
|
23
27
|
gem.add_development_dependency "fuubar", "~> 2.0"
|
24
28
|
gem.add_development_dependency "rspec", "~> 3.12"
|
29
|
+
gem.add_development_dependency "rubocop", "~> 1.54"
|
30
|
+
gem.add_development_dependency "rubocop-rspec", "~> 2.22"
|
31
|
+
gem.add_development_dependency "yard", "~> 0.9"
|
25
32
|
end
|
data/lib/cli/auth.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gistribute
|
4
|
+
class CLI
|
5
|
+
def authenticate
|
6
|
+
access_token = if File.exist?(CONFIG_FILE)
|
7
|
+
File.read(CONFIG_FILE).strip
|
8
|
+
else
|
9
|
+
device_res = URI.decode_www_form(
|
10
|
+
Net::HTTP.post_form(
|
11
|
+
URI("https://github.com/login/device/code"), "client_id" => CLIENT_ID, "scope" => "gist"
|
12
|
+
).body
|
13
|
+
).to_h
|
14
|
+
|
15
|
+
retry_interval = device_res["interval"].to_i
|
16
|
+
|
17
|
+
Launchy.open(device_res["verification_uri"])
|
18
|
+
puts <<~EOS
|
19
|
+
Opening GitHub, please enter the authentication code: #{device_res['user_code']}
|
20
|
+
If your browser did not open, visit #{device_res['verification_uri']}
|
21
|
+
EOS
|
22
|
+
|
23
|
+
uri = URI("https://github.com/login/oauth/access_token")
|
24
|
+
|
25
|
+
# Keep trying until the user enters the code or the device code expires
|
26
|
+
token = nil
|
27
|
+
loop do
|
28
|
+
sleep(retry_interval)
|
29
|
+
|
30
|
+
response = URI.decode_www_form(
|
31
|
+
Net::HTTP.post_form(
|
32
|
+
uri, "client_id" => CLIENT_ID, "device_code" => device_res["device_code"],
|
33
|
+
"grant_type" => "urn:ietf:params:oauth:grant-type:device_code"
|
34
|
+
).body
|
35
|
+
).to_h
|
36
|
+
|
37
|
+
if (token = response["access_token"])
|
38
|
+
File.write(CONFIG_FILE, token)
|
39
|
+
break
|
40
|
+
elsif response["error"] == "authorization_pending"
|
41
|
+
# The user has not yet entered the code; keep waiting silently
|
42
|
+
next
|
43
|
+
elsif response["error"] == "expired_token"
|
44
|
+
panic! "Token expired! Please try again."
|
45
|
+
else
|
46
|
+
panic! response["error_description"]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
token
|
51
|
+
end
|
52
|
+
|
53
|
+
@client = Octokit::Client.new(access_token:)
|
54
|
+
|
55
|
+
success_message = "Logged in as #{@client.user.login}."
|
56
|
+
if @subcommand == "login"
|
57
|
+
puts success_message.green
|
58
|
+
else
|
59
|
+
puts success_message
|
60
|
+
puts
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/lib/cli/install.rb
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gistribute
|
4
|
+
class CLI
|
5
|
+
def install
|
6
|
+
print "Downloading data..."
|
7
|
+
|
8
|
+
id = Gistribute.parse_id(ARGV.first)
|
9
|
+
|
10
|
+
begin
|
11
|
+
gist = @client.gist(id)
|
12
|
+
rescue Octokit::Error => e
|
13
|
+
$stderr.print <<~EOS.chop.red
|
14
|
+
\rThere was an error downloading the requested Gist.
|
15
|
+
The error is as follows:
|
16
|
+
EOS
|
17
|
+
$stderr.puts " #{e.response_status} #{JSON.parse(e.response_body)['message']}"
|
18
|
+
|
19
|
+
$stderr.print "The ID that was queried is: ".red
|
20
|
+
$stderr.puts id
|
21
|
+
|
22
|
+
exit 1
|
23
|
+
end
|
24
|
+
|
25
|
+
# Regular expression word wrap to keep lines less than 80 characters. Then
|
26
|
+
# check to see if it's empty- if not, put newlines on each side so that it
|
27
|
+
# will be padded when displayed in the output.
|
28
|
+
gist_description = gist.description.gsub(/(.{1,79})(\s+|\Z)/, "\\1\n").strip
|
29
|
+
gist_description = "\n#{gist_description}\n" unless gist_description.empty?
|
30
|
+
|
31
|
+
# Process files
|
32
|
+
files = gist.files.map do |filename, data|
|
33
|
+
metadata = filename.to_s.split("||").map(&:strip)
|
34
|
+
|
35
|
+
# | as path separator in the Gist's file name, as Gist doesn't allow the
|
36
|
+
# usage of /.
|
37
|
+
path = Gistribute.decode(metadata.last)
|
38
|
+
# Default description is the name of the file.
|
39
|
+
description = metadata.size == 1 ? File.basename(path) : metadata.first
|
40
|
+
|
41
|
+
{ description:, path:, content: data[:content] }
|
42
|
+
end
|
43
|
+
|
44
|
+
puts <<~EOS
|
45
|
+
\rFinished downloading Gist from: #{gist.html_url}
|
46
|
+
Gist uploaded by #{
|
47
|
+
gist.owner ? "user #{gist.owner[:login]}" : 'an anonymous user'
|
48
|
+
}.
|
49
|
+
#{gist_description}
|
50
|
+
EOS
|
51
|
+
|
52
|
+
unless @subcommand_options.yes
|
53
|
+
puts "Files:"
|
54
|
+
|
55
|
+
files.each do |f|
|
56
|
+
print "#{f[:description]}: " unless f[:description].empty?
|
57
|
+
puts f[:path]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
if @subcommand_options.yes || confirm?("\nWould you like to install these files? [Yn] ")
|
62
|
+
puts unless @subcommand_options.yes
|
63
|
+
|
64
|
+
files.each do |f|
|
65
|
+
if File.exist?(f[:path]) && !@subcommand_options.force &&
|
66
|
+
!confirm?("File already exists: #{f[:path]}\nWould you like to overwrite it? [Yn] ")
|
67
|
+
puts " #{'*'.red} #{f[:description]} skipped."
|
68
|
+
next
|
69
|
+
end
|
70
|
+
|
71
|
+
# Handle directories that don't exist.
|
72
|
+
FileUtils.mkdir_p File.dirname(f[:path])
|
73
|
+
File.write(f[:path], f[:content])
|
74
|
+
|
75
|
+
# If using `--yes`, we print the path in the this string rather than
|
76
|
+
# above with the prompt
|
77
|
+
puts " #{'*'.green} #{f[:description]} installed#{
|
78
|
+
@subcommand_options.yes ? " to: #{f[:path]}" : '.'
|
79
|
+
}"
|
80
|
+
end
|
81
|
+
else
|
82
|
+
puts "Aborting.".red
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/lib/cli/upload.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Gistribute
|
4
|
+
class CLI
|
5
|
+
def upload
|
6
|
+
files_json = process_files(@files)
|
7
|
+
|
8
|
+
if files_json.empty?
|
9
|
+
panic! "No files found, aborting."
|
10
|
+
end
|
11
|
+
|
12
|
+
if @subcommand_options.yes || confirm?("\nUpload these files? [Yn] ")
|
13
|
+
gist = @client.create_gist({
|
14
|
+
description: "[gistribution] #{@subcommand_options.description}".strip,
|
15
|
+
public: !@subcommand_options.private,
|
16
|
+
files: files_json
|
17
|
+
})
|
18
|
+
|
19
|
+
puts if @subcommand_options.yes
|
20
|
+
print "Gistribution uploaded to: ".green
|
21
|
+
puts gist.html_url
|
22
|
+
else
|
23
|
+
puts "Aborted.".red
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def process_files(files)
|
28
|
+
files.each_with_object({}) do |file, hash|
|
29
|
+
hash.merge!(process_file file)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def process_file(file)
|
34
|
+
file = File.expand_path(file)
|
35
|
+
|
36
|
+
if File.directory?(file)
|
37
|
+
# Recursively process every file in the directory
|
38
|
+
process_files(
|
39
|
+
Dir.glob("#{file}/**/*", File::FNM_DOTMATCH).reject { |f| File.directory? f }
|
40
|
+
)
|
41
|
+
else
|
42
|
+
unless (content = File.read(file))
|
43
|
+
panic! "Files cannot be empty."
|
44
|
+
end
|
45
|
+
|
46
|
+
puts "File: #{file}"
|
47
|
+
desc = get_input("Enter pretty file name (leave blank to use raw file name): ")
|
48
|
+
|
49
|
+
# Return a hash directly for single files
|
50
|
+
{ "#{"#{desc} || " unless desc.empty?}#{Gistribute.encode file}" => { content: } }
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|