-
Notifications
You must be signed in to change notification settings - Fork 5
Expand file tree
/
Copy pathfilesystem_project.rb
More file actions
88 lines (73 loc) · 2.84 KB
/
Copy pathfilesystem_project.rb
File metadata and controls
88 lines (73 loc) · 2.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# frozen_string_literal: true
require 'yaml'
class FilesystemProject
CODE_FORMATS = ['.py', '.csv', '.txt', '.html', '.css', '.sb3'].freeze
PROJECTS_ROOT = Rails.root.join('lib/tasks/project_components')
PROJECT_CONFIG = 'project_config.yml'
def self.import_all!
PROJECTS_ROOT.each_child do |dir|
proj_config = YAML.safe_load_file(dir.join(PROJECT_CONFIG).to_s)
files = dir.children.reject { |file| file.basename.to_s == PROJECT_CONFIG }
files = configured_scratch_files(files, proj_config) if proj_config['TYPE'] == Project::Types::CODE_EDITOR_SCRATCH
categorized_files = categorize_files(files, dir)
project_importer = ProjectImporter.new(name: proj_config['NAME'], identifier: proj_config['IDENTIFIER'],
type: proj_config['TYPE'] || Project::Types::PYTHON,
locale: proj_config['LOCALE'] || 'en', **categorized_files)
project_importer.import!
end
end
def self.categorize_files(files, dir)
categories = {
components: [],
images: [],
videos: [],
audio: []
}
files.each do |file|
if CODE_FORMATS.include? File.extname(file)
categories[:components] << component(file, dir)
else
mime_type = file_mime_type(file)
case mime_type
when %r{text|application/javascript}
categories[:components] << component(file, dir)
when /image/
categories[:images] << media(file, dir)
when /video/
categories[:videos] << media(file, dir)
when /audio/
categories[:audio] << media(file, dir)
else
raise "Unsupported file type: #{mime_type}"
end
end
end
categories
end
def self.configured_scratch_files(files, proj_config)
configured_locations = Array(proj_config['COMPONENTS']).pluck('location')
return files if configured_locations.empty?
files.reject { |file| File.extname(file) == '.sb3' && configured_locations.exclude?(file.basename.to_s) }
end
def self.component(file, dir)
name = File.basename(file, '.*')
extension = File.extname(file).delete('.')
return { name:, extension:, file_path: dir.join(File.basename(file)).to_s } if extension == 'sb3'
code = File.read(dir.join(File.basename(file)).to_s)
default = (File.basename(file) == 'main.py')
{ name:, extension:, content: code, default: }
end
def self.file_mime_type(path)
File.open(path) do |file|
Marcel::MimeType.for(file, name: File.basename(path))
end
end
def self.media(file, dir)
filename = File.basename(file)
# rubocop:disable Style/FileOpen
# This is an issue but we can't easily fix it as the returned IO object is used elsewhere.
io = File.open(dir.join(filename).to_s)
# rubocop:enable Style/FileOpen
{ filename:, io: }
end
end