Clearer output, consistently use 'Picopackage'. Handle importing a file converting to a Picopackage. Remove debugger. Add a json_body convenience method. Set the default version to 0.0.1
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
PATH
|
PATH
|
||||||
remote: .
|
remote: .
|
||||||
specs:
|
specs:
|
||||||
picopackage (0.1.0)
|
picopackage (0.2.0)
|
||||||
digest
|
digest
|
||||||
open-uri (~> 0.5)
|
open-uri (~> 0.5)
|
||||||
yaml (~> 0.4)
|
yaml (~> 0.4)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
require_relative "picopackage/version"
|
require_relative "picopackage/version"
|
||||||
|
require_relative "picopackage/http_fetcher"
|
||||||
require_relative "picopackage/provider"
|
require_relative "picopackage/provider"
|
||||||
require_relative "picopackage/source_file"
|
require_relative "picopackage/source_file"
|
||||||
require_relative "picopackage/scanner"
|
require_relative "picopackage/scanner"
|
||||||
@@ -10,5 +11,6 @@ require_relative "picopackage/cli"
|
|||||||
module Picopackage
|
module Picopackage
|
||||||
class Error < StandardError; end
|
class Error < StandardError; end
|
||||||
class FileTooLargeError < StandardError; end
|
class FileTooLargeError < StandardError; end
|
||||||
|
class FetchError < StandardError; end
|
||||||
class LocalModificationError < StandardError; end
|
class LocalModificationError < StandardError; end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -77,14 +77,30 @@ module Picopackage
|
|||||||
end
|
end
|
||||||
|
|
||||||
begin
|
begin
|
||||||
source_file = Fetch.fetch(url, path, force: options[:force])
|
Fetch.fetch(url, path, force: options[:force])
|
||||||
|
rescue LocalModificationError => e
|
||||||
|
puts "Error: #{e.message}"
|
||||||
|
rescue => e
|
||||||
|
puts "Error: #{e.message}"
|
||||||
|
exit 1
|
||||||
|
end
|
||||||
|
|
||||||
|
when 'update'
|
||||||
|
options = { force: false }
|
||||||
|
OptionParser.new do |opts|
|
||||||
|
opts.banner = "Usage: ppkg update [options] FILE"
|
||||||
|
opts.on('-f', '--force', 'Force update') { |f| options[:force] = f }
|
||||||
|
end.parse!(argv)
|
||||||
|
|
||||||
|
file = argv.first
|
||||||
|
source_file = SourceFile.from_file(file)
|
||||||
|
begin
|
||||||
|
Fetch.fetch(source_file.url, path, force: options[:force])
|
||||||
rescue LocalModificationError => e
|
rescue LocalModificationError => e
|
||||||
puts "Error: #{e.message}"
|
puts "Error: #{e.message}"
|
||||||
rescue => e
|
rescue => e
|
||||||
puts "Error: #{e.message}"
|
puts "Error: #{e.message}"
|
||||||
exit 1
|
exit 1
|
||||||
# Optionally retry with force
|
|
||||||
# source_file = Fetch.fetch(url, destination, force: true)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -8,29 +8,37 @@ module Picopackage
|
|||||||
class Fetch
|
class Fetch
|
||||||
def self.fetch(url, destination, force: false)
|
def self.fetch(url, destination, force: false)
|
||||||
raise ArgumentError, "Destination directory does not exist: #{destination}" unless Dir.exist?(destination)
|
raise ArgumentError, "Destination directory does not exist: #{destination}" unless Dir.exist?(destination)
|
||||||
debugger
|
|
||||||
provider = Provider.for(url)
|
provider = Provider.for(url)
|
||||||
file_path = File.join(destination, provider.source_file.filename)
|
source_file = provider.source_file
|
||||||
debugger
|
|
||||||
|
file_path = File.join(destination, source_file.filename)
|
||||||
|
|
||||||
if File.exist?(file_path) && force
|
if File.exist?(file_path) && force
|
||||||
provider.source_file.save(destination)
|
source_file.save(destination)
|
||||||
elsif File.exist?(file_path)
|
elsif File.exist?(file_path)
|
||||||
local_source_file = SourceFile.from_file(file_path)
|
local_source_file = SourceFile.from_file(file_path)
|
||||||
status = Status.compare(local_source_file, provider.source_file)
|
status = Status.compare(local_source_file, source_file)
|
||||||
|
|
||||||
if force
|
if force
|
||||||
provider.source_file.save(destination)
|
source_file.save(destination)
|
||||||
elsif status.modified?
|
elsif status.modified?
|
||||||
raise LocalModificationError, "#{status.message}. Use -f or --force to overwrite local version"
|
raise LocalModificationError, "#{status.message}. Use -f or --force to overwrite local version"
|
||||||
elsif status.outdated?
|
elsif status.outdated?
|
||||||
puts "Updated from #{local_source_file.version} to #{provider.source_file.version}"
|
puts "Updated from #{local_source_file.version} to #{source_file.version}"
|
||||||
provider.source_file.save(destination)
|
source_file.save(destination)
|
||||||
elsif status.up_to_date?
|
elsif status.up_to_date?
|
||||||
puts status.message
|
puts status.message
|
||||||
end
|
end
|
||||||
|
|
||||||
else
|
else
|
||||||
provider.source_file.save(destination)
|
source_file.save(destination)
|
||||||
|
if source_file.imported?
|
||||||
|
source_file.sign
|
||||||
|
puts "Picopackage created for #{source_file.filename}"
|
||||||
|
else
|
||||||
|
puts "Picopackage downloaded to #{file_path}"
|
||||||
|
end
|
||||||
end
|
end
|
||||||
provider.source_file
|
provider.source_file
|
||||||
end
|
end
|
||||||
@@ -82,15 +90,15 @@ debugger
|
|||||||
def message
|
def message
|
||||||
case state
|
case state
|
||||||
when :up_to_date
|
when :up_to_date
|
||||||
"File is up to date"
|
"Picopackage is up to date"
|
||||||
when :outdated
|
when :outdated
|
||||||
if modified?
|
if modified?
|
||||||
"Local file (v#{local_version}) has modifications but remote version (v#{remote_version}) is available"
|
"Local Picopackage (v#{local_version}) has modifications but remote version (v#{remote_version}) is available"
|
||||||
else
|
else
|
||||||
"Local file (v#{local_version}) is outdated. Remote version: v#{remote_version}"
|
"Local Picopackage (v#{local_version}) is outdated. Remote version: v#{remote_version}"
|
||||||
end
|
end
|
||||||
when :modified
|
when :modified
|
||||||
"Local file has been modified from original version (v#{local_version})"
|
"Local Picopackage has been modified from original version (v#{local_version})"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -28,7 +28,6 @@ module Picopackage
|
|||||||
class DefaultProvider
|
class DefaultProvider
|
||||||
MAX_SIZE = 1024 * 1024
|
MAX_SIZE = 1024 * 1024
|
||||||
TIMEOUT = 10
|
TIMEOUT = 10
|
||||||
|
|
||||||
attr_reader :url, :source_file
|
attr_reader :url, :source_file
|
||||||
|
|
||||||
def self.handles_url?(url) = :maybe
|
def self.handles_url?(url) = :maybe
|
||||||
@@ -44,6 +43,8 @@ module Picopackage
|
|||||||
|
|
||||||
def body = @body ||= fetch
|
def body = @body ||= fetch
|
||||||
|
|
||||||
|
def json_body = @json_body ||= JSON.parse(body)
|
||||||
|
|
||||||
def fetch
|
def fetch
|
||||||
begin
|
begin
|
||||||
Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.scheme == 'https', read_timeout: TIMEOUT, open_timeout: TIMEOUT) do |http|
|
Net::HTTP.start(@uri.host, @uri.port, use_ssl: @uri.scheme == 'https', read_timeout: TIMEOUT, open_timeout: TIMEOUT) do |http|
|
||||||
@@ -71,7 +72,9 @@ module Picopackage
|
|||||||
end
|
end
|
||||||
|
|
||||||
def content
|
def content
|
||||||
# Implement in subclass - this come from the `body`. Spliting content into code and metadata is the job of the SourceFile class
|
# Implement in subclass - this come from the `body`.
|
||||||
|
# Spliting content into code and metadata is the job of the SourceFile class
|
||||||
|
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -81,7 +84,9 @@ module Picopackage
|
|||||||
end
|
end
|
||||||
|
|
||||||
def source_file
|
def source_file
|
||||||
@source_file ||= SourceFile.from_content(content)
|
@source_file ||= SourceFile.from_content(
|
||||||
|
content, metadata: {'filename' => filename, 'url' => url, 'version' => '0.0.1'}
|
||||||
|
)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -93,15 +98,9 @@ module Picopackage
|
|||||||
"https://api.github.com/gists/#{gist_id}"
|
"https://api.github.com/gists/#{gist_id}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def content
|
def content = json_body["files"].values.first["content"]
|
||||||
data = JSON.parse(body)
|
|
||||||
file = data["files"].values.first["content"]
|
|
||||||
end
|
|
||||||
|
|
||||||
def filename
|
def filename = json_body["files"].values.first["filename"]
|
||||||
data = JSON.parse(body)
|
|
||||||
data["files"].values.first["filename"]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class OpenGistProvider < DefaultProvider
|
class OpenGistProvider < DefaultProvider
|
||||||
@@ -109,19 +108,11 @@ module Picopackage
|
|||||||
:maybe
|
:maybe
|
||||||
end
|
end
|
||||||
|
|
||||||
def transform_url(url)
|
def transform_url(url) = "#{url}.json"
|
||||||
"#{url}.json"
|
|
||||||
end
|
|
||||||
|
|
||||||
def content
|
def content = json_body.dig("files",0, "content")
|
||||||
data = JSON.parse(body)
|
|
||||||
@content = data.dig("files",0, "content")
|
|
||||||
end
|
|
||||||
|
|
||||||
def filename
|
def filename = json_body.dig("files",0, "filename")
|
||||||
data = JSON.parse(body)
|
|
||||||
data.dig("files",0, "filename")
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
PROVIDERS = [
|
PROVIDERS = [
|
||||||
|
|||||||
@@ -9,12 +9,15 @@ module Picopackage
|
|||||||
|
|
||||||
def self.from_file(file_path) = new(content: File.read(file_path), original_path: file_path)
|
def self.from_file(file_path) = new(content: File.read(file_path), original_path: file_path)
|
||||||
|
|
||||||
def self.from_content(content, filename: nil)
|
def self.from_content(content, metadata: {})
|
||||||
instance = new(content: content)
|
instance = new(content: content)
|
||||||
if filename && !instance.metadata['filename']
|
instance.imported! if instance.metadata.empty?
|
||||||
metadata = instance.metadata.merge('filename' => filename)
|
|
||||||
instance.update_metadata(metadata) #TODO: FIX THIS
|
updated_metadata = metadata.merge(instance.metadata)
|
||||||
end
|
|
||||||
|
## For new Picopackages, we should add metadata and sign
|
||||||
|
instance.update_metadata(updated_metadata)
|
||||||
|
|
||||||
instance
|
instance
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -26,9 +29,17 @@ module Picopackage
|
|||||||
@code = extract_code
|
@code = extract_code
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def imported! = @imported = true
|
||||||
|
|
||||||
|
def imported? = @imported ||= false
|
||||||
|
|
||||||
|
def content = @content
|
||||||
|
|
||||||
|
def url = @metadata['url']
|
||||||
|
|
||||||
def filename = @metadata['filename']
|
def filename = @metadata['filename']
|
||||||
|
|
||||||
def version = @metadata['version'] || '0.0.0'
|
def version = @metadata['version'] || '0.0.1'
|
||||||
|
|
||||||
def checksum = "sha256:#{Digest::SHA256.hexdigest(code)}"
|
def checksum = "sha256:#{Digest::SHA256.hexdigest(code)}"
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user