diff --git a/bin/dat b/bin/dat index ce39498..b6fd0fb 100755 --- a/bin/dat +++ b/bin/dat @@ -12,6 +12,7 @@ options = OpenStruct.new # take the first so OptionParser will not see it subcommand = ARGV.shift&.to_sym +options.name = ARGV[0] && ARGV[0] !~ /^-/ ? ARGV.shift : nil OptionParser.new do |opt| opt.on('-i', '--install', 'Install dat for the user') { |o| options.type = :install } diff --git a/lib/archive.rb b/lib/archive.rb index 3f71694..6729d76 100644 --- a/lib/archive.rb +++ b/lib/archive.rb @@ -13,7 +13,17 @@ module Archive "\xFD\x37\x7A\x58" => 'xz' } - def self.fetch_and_extract(url, cache_path, destination_dir) + def self.extract(archive_path, destination_dir) + format = detect_format_from_url(archive_path) + + unless format + format = detect_format_from_magic(archive_path) + end + + extract_archive(archive_path, destination_dir, format) + end + + def self.fetch_and_extract(url, cache_path, destination_dir) uri = URI.parse(url) file_name = File.basename(uri.path) archive_path = File.join(destination_dir, file_name) @@ -21,7 +31,8 @@ module Archive format = detect_format_from_url(url) puts "format #{format}" download_file(uri, archive_path) - + + # Probably do not work unless format puts "case 1" format = detect_format_from_headers(uri) @@ -37,6 +48,20 @@ module Archive extract_archive(archive_path, format) end + def self.download_file(uri, output_path, forced=false) + return if File.exist?(output_path) && !forced + + # Ensure the directory exists + dir = File.dirname(output_path) + FileUtils.mkdir_p(dir) unless Dir.exist?(dir) + + URI.open(uri) do |input| + File.open(output_path, 'wb') do |output| + IO.copy_stream(input, output) + end + end + end + private def self.detect_format_from_url(url) @@ -71,33 +96,60 @@ module Archive nil end - def self.download_file(uri, output_path) - URI.open(uri) do |input| - File.open(output_path, 'wb') do |output| - IO.copy_stream(input, output) - end + + require 'shellwords' + + def self.extract_archive(file_path, destination_dir, format) + # TODO: need to be checked + escaped_file = Shellwords.escape(file_path) + escaped_dir = Shellwords.escape(destination_dir) + + system("mkdir -p #{escaped_dir}") + + case format + when 'gzip' + system("tar -xzf #{escaped_file} -C #{escaped_dir}") + when 'zip' + system("unzip -d #{escaped_dir} #{escaped_file}") + when 'zstd' + if `file #{escaped_file}`.include?('tar archive') + system("unzstd -c #{escaped_file} | tar -xf - -C #{escaped_dir}") + else + system("unzstd -o \"#{escaped_dir}\" #{escaped_file}") end + when 'xz' + if `file #{escaped_file}`.include?('tar archive') + system("tar -xJf #{escaped_file} -C #{escaped_dir}") + else + system("xz -dk #{escaped_file}") + decompressed = file_path.sub(/\.xz$/, '') + system("mv #{Shellwords.escape(decompressed)} #{escaped_dir}/") + end + else + raise "Unsupported archive format: #{format}" + end end - def self.extract_archive(file_path, format) - case format - when 'gzip' - system("tar -xzf #{Shellwords.escape(file_path)}") - when 'zip' - system("unzip #{Shellwords.escape(file_path)}") - when 'zstd' - system("unzstd #{Shellwords.escape(file_path)}") - when 'xz' - # if file_path.end_with?('.tar.xz') - if `file #{Shellwords.escape(file_path)}`.include?('tar archive') - system("tar -xJf #{Shellwords.escape(file_path)}") - else - system("xz -dk #{Shellwords.escape(file_path)}") - end - else - raise "Unsupported archive format: #{format}" - end - end + + # def self.extract_archive(file_path, destination_dir, format) + # case format + # when 'gzip' + # system("tar -xzf #{Shellwords.escape(file_path)}") + # when 'zip' + # system("unzip #{Shellwords.escape(file_path)}") + # when 'zstd' + # system("unzstd #{Shellwords.escape(file_path)}") + # when 'xz' + # # if file_path.end_with?('.tar.xz') + # if `file #{Shellwords.escape(file_path)}`.include?('tar archive') + # system("tar -xJf #{Shellwords.escape(file_path)}") + # else + # system("xz -dk #{Shellwords.escape(file_path)}") + # end + # else + # raise "Unsupported archive format: #{format}" + # end + # end end # Example usage: # fetch_and_extract("https://codeberg.org/forgejo/forgejo/releases/download/v12.0.1/forgejo-12.0.1-linux-amd64.xz") diff --git a/lib/make.rb b/lib/make.rb index b8330b1..3a324d7 100644 --- a/lib/make.rb +++ b/lib/make.rb @@ -123,6 +123,12 @@ module Make "#{ENV["HOME"]}/.cache/dat/repo/#{@name}.git" end + def download_path + require 'addressable/uri' + uri = Addressable::URI.parse(archive.url) + File.join("#{ENV["HOME"]}/.cache/dat/downloads/", uri.domain, uri.path) + end + def to_s vars = instance_variables.map do |var| "#{var.to_s.delete('@')}: #{instance_variable_get(var).inspect}" @@ -184,10 +190,16 @@ module Make end def download_and_extract - archive = @context.archive + # gem install addressable + + archive = @context.archive + puts @context.download_path puts archive - exit -1 + + require 'archive' + Archive.download_file(@context.archive.url, @context.download_path) + Archive.extract(@context.download_path, @cwd) end def checkout diff --git a/recipes/forgejo-recipe/debian.yml b/recipes/forgejo-recipe/debian.yml index fb41220..0159ae8 100644 --- a/recipes/forgejo-recipe/debian.yml +++ b/recipes/forgejo-recipe/debian.yml @@ -3,4 +3,4 @@ archive: url: https://codeberg.org/forgejo/forgejo/releases/download/v12.0.1/forgejo-12.0.1-linux-amd64.xz steps: - - echo "ls" + - mv forgejo-12.0.1-linux-amd64 ~/.local/bin/forgejo