Skip to content

Commit

Permalink
archive: update unarchive script to handle git repositories
Browse files Browse the repository at this point in the history
  • Loading branch information
mishaschwartz committed Jan 6, 2023
1 parent dae7981 commit 6e9cb13
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 4 deletions.
2 changes: 2 additions & 0 deletions app/models/group.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ def repo_path
# Git repos are stored on disk but not other types of repo (ie. memory)
if Settings.repository.type == 'git'
def _file_location
return if self.course.nil?

Repository.get_class.respond_to?(:bare_path) ? Repository.get_class.bare_path(repo_path) : repo_path
end
end
Expand Down
14 changes: 12 additions & 2 deletions lib/archive_tools/course_archiver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -294,9 +294,11 @@ def unarchive(archive_file, tmp_db_url: nil)
record = klass.new(attributes)

# Get the old file location before updating foreign keys so that file locations dependant on
# associated records are calculated correctly.
# foreign key values are calculated correctly. This works for files whose location is dependant
# on foreign keys (eg: starter file group files), but not for files whose location is dependant
# on associated records themselves (eg: group repositories); these are discovered after the new
# record is created in the database.
old_file_location = nil
new_file_location = nil
if record.respond_to? :_file_location
old_file_location = temporary_file_storage(data_dir) { record._file_location }
end
Expand All @@ -315,6 +317,14 @@ def unarchive(archive_file, tmp_db_url: nil)
record.assign_attributes(k => new_ids[associated_class.table_name][v.to_s])
end

if record.respond_to?(:_file_location) && !File.exist?(old_file_location.to_s)
# The file may not exist if the location is dependant on the existence of an
# associated object in the database (eg: group repositories' locations depend on
# the course name). That object may not have existed yet the last time that
# old_file_location was calculated
old_file_location = temporary_file_storage(data_dir) { record._file_location }
end

# nullify the id so that it can be assigned a new one.
# insert is used so that callbacks and validations are not run
result = klass.insert(record.attributes.except('id'),
Expand Down
Binary file not shown.
17 changes: 15 additions & 2 deletions spec/lib/archive_tools/course_archiver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

describe ArchiveTools::CourseArchiver do
include ArchiveTools::CourseArchiver
let(:repo_type) { 'mem' }
before { allow(Settings.repository).to receive(:type).and_return(repo_type) }

let(:full_course) do
course = create :course
create :assignment_with_criteria_and_test_results, course: course
Expand Down Expand Up @@ -51,7 +54,6 @@
expect(archived_course_id).to eq course.id.to_s
end
it 'contains the expected db files' do
subject
Rails.application.eager_load!
files = ApplicationRecord.descendants
.reject { |klass| ids_associated_to_course(course, klass).empty? }
Expand All @@ -60,7 +62,6 @@
expect(archived_db_data.map { |f| File.basename(f) }).to contain_exactly(*files)
end
it 'contains the expected data files' do
subject
Rails.application.eager_load!
allow(Settings).to receive(:file_storage).and_return Config::Options.new(default_root_path: archived_file_loc)
files = ApplicationRecord.descendants
Expand All @@ -78,6 +79,11 @@
context 'a full course' do
let(:course) { full_course }
it_behaves_like 'archive course'
context 'with git repositories', :keep_memory_repos do
let(:repo_type) { 'git' }
after { FileUtils.rm_r(Dir.glob(File.join(Repository.root_dir, '*'))) }
it_behaves_like 'archive course'
end
end
context 'when other courses exist' do
let(:course) { create :course }
Expand Down Expand Up @@ -169,6 +175,13 @@
context 'using a full valid archive file' do
it_behaves_like 'unarchive course'
it_behaves_like 'cleanup after'
context 'with git repositories', :keep_memory_repos do
let(:archive_file) { Rails.root.join('spec/fixtures/files/unarchive/good_full_git.tar.gz') }
let(:repo_type) { 'git' }
after { FileUtils.rm_r(Dir.glob(File.join(Repository.root_dir, '*'))) }
it_behaves_like 'unarchive course'
it_behaves_like 'cleanup after'
end
end
context 'using an archive file with missing data' do
before do
Expand Down

0 comments on commit 6e9cb13

Please sign in to comment.