Skip to content

Commit

Permalink
Merge 1486349 into d193d7d
Browse files Browse the repository at this point in the history
  • Loading branch information
mjacobus committed Apr 6, 2020
2 parents d193d7d + 1486349 commit 7429d9d
Show file tree
Hide file tree
Showing 13 changed files with 559 additions and 1 deletion.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
# rspec failure tracking
.rspec_status
/Gemfile.lock
/spec/fixtures/sandbox
6 changes: 5 additions & 1 deletion lib/koine/file_system.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# frozen_string_literal: true

require 'koine/file_system/version'
require 'koine/file_system/file_system'
require 'koine/file_system/path_sanitizer'
require 'koine/file_system/adapters/base'
require 'koine/file_system/adapters/local'

module Koine
module FileSystem
class Error < StandardError; end
# Your code goes here...
class FileNotFound < Error; end
end
end
85 changes: 85 additions & 0 deletions lib/koine/file_system/adapters/base.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# frozen_string_literal: true

module Koine
module FileSystem
module Adapters
# rubocop:disable Lint/UnusedMethodArgument
class Base
def read(_path)
raise NotImplementedError
end

def read_stream(_path)
raise NotImplementedError
end

def write(_path, _contents, options: {})
raise NotImplementedError
end

def write_stream(_path, _contents, options: {})
raise NotImplementedError
end

def update(_path, _contents, options: {})
raise NotImplementedError
end

def update_stream(_path, _contents, options: {})
raise NotImplementedError
end

def has?(_path)
raise NotImplementedError
end

def delete(_path)
raise NotImplementedError
end

def read_and_delete(_path)
raise NotImplementedError
end

def rename(_from, _to)
raise NotImplementedError
end

def copy(_from, _to)
raise NotImplementedError
end

def mime_type(_path)
raise NotImplementedError
end

def size(_path)
raise NotImplementedError
end

def create_dir(_path)
raise NotImplementedError
end

def delete_dir(_path)
raise NotImplementedError
end

def list_contents(_path)
raise NotImplementedError
end

def list(_path, recursive: false)
raise NotImplementedError
end

private

def raise_not_found(file)
raise FileNotFound, "File not found: #{file}"
end
end
# rubocop:enable Lint/UnusedMethodArgument
end
end
end
73 changes: 73 additions & 0 deletions lib/koine/file_system/adapters/local.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# frozen_string_literal: true

require 'fileutils'

module Koine
module FileSystem
module Adapters
class Local < Base
def initialize(root:, path_sanitizer: PathSanitizer.new)
@root = root
@path_sanitizer = path_sanitizer
end

def read(path)
if has?(path)
file = File.open(full_path(path), 'rb')
content = file.read
file.close
return content
# return File.read(full_path(path))
end
raise_not_found(path)
end

def has?(path)
File.exist?(full_path(path))
end

def write(path, content, options: {})
path = full_path(path)
ensure_target_dir(path)
File.open(path, 'w') do |f|
f.write(content)
end
end

private

def full_path(path)
File.expand_path(sanitize_path(path), @root)
end

def ensure_target_dir(path)
dir = File.dirname(path)
unless Dir.exist?(dir)
FileUtils.mkdir_p(dir)
end
end

def sanitize_path(path)
@path_sanitizer.sanitize(path)
end

# def read_stream(_path)
# def write(_path, _contents, options: {})
# def write_stream(_path, _contents, options: {})
# def update(_path, _contents, options: {})
# def update_stream(_path, _contents, options: {})
# def has?(_path)
# def delete(_path)
# def read_and_delete(_path)
# def rename(_from, _to)
# def copy(_from, _to)
# def mime_type(_path)
# def size(_path)
# def create_dir(_path)
# def delete_dir(_path)
# def list_contents(_path)
# def list(_path, recursive: false)
end
end
end
end
77 changes: 77 additions & 0 deletions lib/koine/file_system/file_system.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# frozen_string_literal: true

module Koine
module FileSystem
# Inspired on
# https://flysystem.thephpleague.com/v1/docs/usage/filesystem-api/
class FileSystem
def initialize(adapter)
@adapter = adapter
end

def read(path, &block)
@adapter.read(path, &block)
end

def read_stream(path, &block)
@adapter.read_stream(path, &block)
end

def write(path, contents, options: {})
@adapter.write(path, contents, options: options)
end

def write_stream(path, contents, options: {})
@adapter.write_stream(path, contents, options: options)
end

def update(path, contents, options: {})
@adapter.update(path, contents, options: options)
end

def update_stream(path, contents, options: {})
@adapter.update_stream(path, contents, options: options)
end

def has?(path)
@adapter.has?(path)
end

def delete(path)
@adapter.delete(path)
end

def read_and_delete(path)
@adapter.read_and_delete(path)
end

def rename(from, to)
@adapter.rename(from, to)
end

def copy(from, to)
@adapter.copy(from, to)
end

def mime_type(path)
@adapter.mime_type(path)
end

def size(path)
@adapter.size(path)
end

def create_dir(path)
@adapter.create_dir(path)
end

def delete_dir(path)
@adapter.delete_dir(path)
end

def list(path, recursive: false)
@adapter.list(path, recursive: recursive)
end
end
end
end
13 changes: 13 additions & 0 deletions lib/koine/file_system/path_sanitizer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# frozen_string_literal: true

require 'fileutils'

module Koine
module FileSystem
class PathSanitizer
def sanitize(path)
path.to_s.gsub('/../', '/').gsub(%r{\.?\./}, '')
end
end
end
end
Empty file added spec/fixtures/sample.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions spec/fixtures/sample.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
This is a sample file
For local adapter
85 changes: 85 additions & 0 deletions spec/koine/file_system/adapters/base_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe Koine::FileSystem::Adapters::Base do
subject(:adapter) { described_class.new }

let(:path) { 'foo' }
let(:contents) { 'bar' }
let(:options) { {} }
let(:from) { 'from' }
let(:to) { 'to' }

# rubocop:disable RSpec/ExampleLength
it 'raises on every method' do
expect do
adapter.read(path)
end.to raise_error(NotImplementedError)

expect do
adapter.read_stream(path)
end.to raise_error(NotImplementedError)

expect do
adapter.write(path, contents, options: {})
end.to raise_error(NotImplementedError)

expect do
adapter.write_stream(path, contents, options: {})
end.to raise_error(NotImplementedError)

expect do
adapter.update(path, contents, options: {})
end.to raise_error(NotImplementedError)

expect do
adapter.update_stream(path, contents, options: {})
end.to raise_error(NotImplementedError)

expect do
adapter.has?(path)
end.to raise_error(NotImplementedError)

expect do
adapter.delete(path)
end.to raise_error(NotImplementedError)

expect do
adapter.read_and_delete(path)
end.to raise_error(NotImplementedError)

expect do
adapter.rename(from, to)
end.to raise_error(NotImplementedError)

expect do
adapter.copy(from, to)
end.to raise_error(NotImplementedError)

expect do
adapter.mime_type(path)
end.to raise_error(NotImplementedError)

expect do
adapter.size(path)
end.to raise_error(NotImplementedError)

expect do
adapter.create_dir(path)
end.to raise_error(NotImplementedError)

expect do
adapter.delete_dir(path)
end.to raise_error(NotImplementedError)

expect do
adapter.list_contents(path)
end.to raise_error(NotImplementedError)

expect do
adapter.list(path, recursive: false)
end.to raise_error(NotImplementedError)
end
# rubocop:enable RSpec/ExampleLength
end
Loading

0 comments on commit 7429d9d

Please sign in to comment.